167 | | i2c_bus bus; |
168 | | bus.cookie = (void*)INTEL_I2C_IO_A; |
169 | | bus.set_signals = &set_i2c_signals; |
170 | | bus.get_signals = &get_i2c_signals; |
171 | | ddc2_init_timing(&bus); |
172 | | |
173 | | status_t error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL); |
174 | | if (error == B_OK) { |
| 173 | // TODO: We may want to choose different GPIO pin maps |
| 174 | // for different generations of cards... not sure |
| 175 | const gpio_map gpioPinMap[] = { |
| 176 | {"ssc", INTEL_I2C_IO_B, 0}, |
| 177 | {"vga", INTEL_I2C_IO_A, HEAD_MODE_A_ANALOG}, |
| 178 | {"lvds", INTEL_I2C_IO_C, HEAD_MODE_LVDS_PANEL}, |
| 179 | {"dpc", INTEL_I2C_IO_D, 0}, |
| 180 | {"dpb", INTEL_I2C_IO_E, 0}, |
| 181 | {"dpd", INTEL_I2C_IO_F, 0}, |
| 182 | }; |
| 183 | |
| 184 | // TODO: We may want to do extra validation on gpio validOn |
| 185 | // vs the HEAD_MODE_ in head_mode |
| 186 | for (uint32 i = 0; i < sizeof(gpioPinMap) |
| 187 | / sizeof(gpioPinMap[0]); i++) { |
| 188 | |
| 189 | i2c_bus bus; |
| 190 | bus.cookie = (void*)gpioPinMap[i].pin; |
| 191 | bus.set_signals = &set_i2c_signals; |
| 192 | bus.get_signals = &get_i2c_signals; |
| 193 | ddc2_init_timing(&bus); |
| 194 | |
| 195 | status_t result = ddc2_read_edid1(&bus, &gInfo->edid_info, |
| 196 | NULL, NULL); |
| 197 | |
| 198 | if (result != B_OK) |
| 199 | continue; |
| 200 | |
| 201 | TRACE("found edid data on gpio '%s'\n", |
| 202 | gpioPinMap[i].name); |
177 | | } else { |
178 | | TRACE("getting EDID on port A (analog) failed : %s. " |
179 | | "Trying on port C (lvds)\n", strerror(error)); |
180 | | bus.cookie = (void*)INTEL_I2C_IO_C; |
181 | | error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL); |
182 | | if (error == B_OK) { |
183 | | edid_dump(&gInfo->edid_info); |
184 | | gInfo->has_edid = true; |
185 | | } else { |
186 | | TRACE("getting EDID on port C failed : %s\n", |
187 | | strerror(error)); |
188 | | |
189 | | // We could not read any EDID info. Fallback to creating a list with |
190 | | // only the mode set up by the BIOS. |
191 | | // TODO: support lower modes via scaling and windowing |
192 | | if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0 |
193 | | && (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) { |
194 | | size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1) |
195 | | & ~(B_PAGE_SIZE - 1); |
196 | | |
197 | | display_mode* list; |
198 | | area_id area = create_area("intel extreme modes", |
199 | | (void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK, |
200 | | B_READ_AREA | B_WRITE_AREA); |
201 | | if (area < B_OK) |
202 | | return area; |
203 | | |
204 | | memcpy(list, &gInfo->lvds_panel_mode, sizeof(display_mode)); |
205 | | |
206 | | gInfo->mode_list_area = area; |
207 | | gInfo->mode_list = list; |
208 | | gInfo->shared_info->mode_list_area = gInfo->mode_list_area; |
209 | | gInfo->shared_info->mode_count = 1; |
210 | | return B_OK; |
211 | | } |
| 205 | |
| 206 | // TODO: We may want to probe multiple GPIO pins here |
| 207 | // someday and store valid ones for multi-head support. |
| 208 | // For now, we break on the first valid one. |
| 209 | break; |
| 210 | } |
| 211 | |
| 212 | if (!gInfo->has_edid) { |
| 213 | // We could not read any EDID info. |
| 214 | if ((gInfo->head_mode & HEAD_MODE_LVDS_PANEL) != 0 |
| 215 | && (gInfo->head_mode & HEAD_MODE_A_ANALOG) == 0) { |
| 216 | // If LVDS, fallback to lvds_panel_mode |
| 217 | size_t size = (sizeof(display_mode) + B_PAGE_SIZE - 1) |
| 218 | & ~(B_PAGE_SIZE - 1); |
| 219 | |
| 220 | display_mode* list; |
| 221 | area_id area = create_area("intel extreme modes", |
| 222 | (void**)&list, B_ANY_ADDRESS, size, B_NO_LOCK, |
| 223 | B_READ_AREA | B_WRITE_AREA); |
| 224 | if (area < B_OK) |
| 225 | return area; |
| 226 | |
| 227 | memcpy(list, &gInfo->lvds_panel_mode, sizeof(display_mode)); |
| 228 | |
| 229 | gInfo->mode_list_area = area; |
| 230 | gInfo->mode_list = list; |
| 231 | gInfo->shared_info->mode_list_area = gInfo->mode_list_area; |
| 232 | gInfo->shared_info->mode_count = 1; |
| 233 | return B_OK; |