1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include "radeonfb.h" |
3 | |
4 | #include <linux/slab.h> |
5 | |
6 | #include "../edid.h" |
7 | |
8 | static const struct fb_var_screeninfo radeonfb_default_var = { |
9 | .xres = 640, |
10 | .yres = 480, |
11 | .xres_virtual = 640, |
12 | .yres_virtual = 480, |
13 | .bits_per_pixel = 8, |
14 | .red = { .length = 8 }, |
15 | .green = { .length = 8 }, |
16 | .blue = { .length = 8 }, |
17 | .activate = FB_ACTIVATE_NOW, |
18 | .height = -1, |
19 | .width = -1, |
20 | .pixclock = 39721, |
21 | .left_margin = 40, |
22 | .right_margin = 24, |
23 | .upper_margin = 32, |
24 | .lower_margin = 11, |
25 | .hsync_len = 96, |
26 | .vsync_len = 2, |
27 | .vmode = FB_VMODE_NONINTERLACED |
28 | }; |
29 | |
30 | static char *radeon_get_mon_name(int type) |
31 | { |
32 | char *pret = NULL; |
33 | |
34 | switch (type) { |
35 | case MT_NONE: |
36 | pret = "no" ; |
37 | break; |
38 | case MT_CRT: |
39 | pret = "CRT" ; |
40 | break; |
41 | case MT_DFP: |
42 | pret = "DFP" ; |
43 | break; |
44 | case MT_LCD: |
45 | pret = "LCD" ; |
46 | break; |
47 | case MT_CTV: |
48 | pret = "CTV" ; |
49 | break; |
50 | case MT_STV: |
51 | pret = "STV" ; |
52 | break; |
53 | } |
54 | |
55 | return pret; |
56 | } |
57 | |
58 | |
59 | #if defined(CONFIG_PPC) || defined(CONFIG_SPARC) |
60 | /* |
61 | * Try to find monitor informations & EDID data out of the Open Firmware |
62 | * device-tree. This also contains some "hacks" to work around a few machine |
63 | * models with broken OF probing by hard-coding known EDIDs for some Mac |
64 | * laptops internal LVDS panel. (XXX: not done yet) |
65 | */ |
66 | static int radeon_parse_montype_prop(struct device_node *dp, u8 **out_EDID, |
67 | int hdno) |
68 | { |
69 | static char *propnames[] = { "DFP,EDID" , "LCD,EDID" , "EDID" , |
70 | "EDID1" , "EDID2" , NULL }; |
71 | const u8 *pedid = NULL; |
72 | const u8 *pmt = NULL; |
73 | u8 *tmp; |
74 | int i, mt = MT_NONE; |
75 | |
76 | pr_debug("analyzing OF properties...\n" ); |
77 | pmt = of_get_property(dp, "display-type" , NULL); |
78 | if (!pmt) |
79 | return MT_NONE; |
80 | pr_debug("display-type: %s\n" , pmt); |
81 | /* OF says "LCD" for DFP as well, we discriminate from the caller of this |
82 | * function |
83 | */ |
84 | if (!strcmp(pmt, "LCD" ) || !strcmp(pmt, "DFP" )) |
85 | mt = MT_DFP; |
86 | else if (!strcmp(pmt, "CRT" )) |
87 | mt = MT_CRT; |
88 | else { |
89 | if (strcmp(pmt, "NONE" ) != 0) |
90 | printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n" , |
91 | pmt); |
92 | return MT_NONE; |
93 | } |
94 | |
95 | for (i = 0; propnames[i] != NULL; ++i) { |
96 | pedid = of_get_property(dp, propnames[i], NULL); |
97 | if (pedid != NULL) |
98 | break; |
99 | } |
100 | /* We didn't find the EDID in the leaf node, some cards will actually |
101 | * put EDID1/EDID2 in the parent, look for these (typically M6 tipb). |
102 | * single-head cards have hdno == -1 and skip this step |
103 | */ |
104 | if (pedid == NULL && dp->parent && (hdno != -1)) |
105 | pedid = of_get_property(dp->parent, |
106 | (hdno == 0) ? "EDID1" : "EDID2" , NULL); |
107 | if (pedid == NULL && dp->parent && (hdno == 0)) |
108 | pedid = of_get_property(dp->parent, "EDID" , NULL); |
109 | if (pedid == NULL) |
110 | return mt; |
111 | |
112 | tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); |
113 | if (!tmp) |
114 | return mt; |
115 | *out_EDID = tmp; |
116 | return mt; |
117 | } |
118 | |
119 | static int radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_no, |
120 | u8 **out_EDID) |
121 | { |
122 | struct device_node *dp; |
123 | |
124 | pr_debug("radeon_probe_OF_head\n" ); |
125 | |
126 | dp = rinfo->of_node; |
127 | while (dp == NULL) |
128 | return MT_NONE; |
129 | |
130 | if (rinfo->has_CRTC2) { |
131 | const char *pname; |
132 | int len, second = 0; |
133 | |
134 | dp = dp->child; |
135 | do { |
136 | if (!dp) |
137 | return MT_NONE; |
138 | pname = of_get_property(dp, "name" , NULL); |
139 | if (!pname) |
140 | return MT_NONE; |
141 | len = strlen(pname); |
142 | pr_debug("head: %s (letter: %c, head_no: %d)\n" , |
143 | pname, pname[len-1], head_no); |
144 | if (pname[len-1] == 'A' && head_no == 0) { |
145 | int mt = radeon_parse_montype_prop(dp, out_EDID, 0); |
146 | /* Maybe check for LVDS_GEN_CNTL here ? I need to check out |
147 | * what OF does when booting with lid closed |
148 | */ |
149 | if (mt == MT_DFP && rinfo->is_mobility) |
150 | mt = MT_LCD; |
151 | return mt; |
152 | } else if (pname[len-1] == 'B' && head_no == 1) |
153 | return radeon_parse_montype_prop(dp, out_EDID, 1); |
154 | second = 1; |
155 | dp = dp->sibling; |
156 | } while(!second); |
157 | } else { |
158 | if (head_no > 0) |
159 | return MT_NONE; |
160 | return radeon_parse_montype_prop(dp, out_EDID, -1); |
161 | } |
162 | return MT_NONE; |
163 | } |
164 | #endif /* CONFIG_PPC || CONFIG_SPARC */ |
165 | |
166 | |
167 | static int radeon_get_panel_info_BIOS(struct radeonfb_info *rinfo) |
168 | { |
169 | unsigned long tmp, tmp0; |
170 | char stmp[30]; |
171 | int i; |
172 | |
173 | if (!rinfo->bios_seg) |
174 | return 0; |
175 | |
176 | if (!(tmp = BIOS_IN16(rinfo->fp_bios_start + 0x40))) { |
177 | printk(KERN_ERR "radeonfb: Failed to detect DFP panel info using BIOS\n" ); |
178 | rinfo->panel_info.pwr_delay = 200; |
179 | return 0; |
180 | } |
181 | |
182 | for(i=0; i<24; i++) |
183 | stmp[i] = BIOS_IN8(tmp+i+1); |
184 | stmp[24] = 0; |
185 | printk("radeonfb: panel ID string: %s\n" , stmp); |
186 | rinfo->panel_info.xres = BIOS_IN16(tmp + 25); |
187 | rinfo->panel_info.yres = BIOS_IN16(tmp + 27); |
188 | printk("radeonfb: detected LVDS panel size from BIOS: %dx%d\n" , |
189 | rinfo->panel_info.xres, rinfo->panel_info.yres); |
190 | |
191 | rinfo->panel_info.pwr_delay = BIOS_IN16(tmp + 44); |
192 | pr_debug("BIOS provided panel power delay: %d\n" , rinfo->panel_info.pwr_delay); |
193 | if (rinfo->panel_info.pwr_delay > 2000 || rinfo->panel_info.pwr_delay <= 0) |
194 | rinfo->panel_info.pwr_delay = 2000; |
195 | |
196 | /* |
197 | * Some panels only work properly with some divider combinations |
198 | */ |
199 | rinfo->panel_info.ref_divider = BIOS_IN16(tmp + 46); |
200 | rinfo->panel_info.post_divider = BIOS_IN8(tmp + 48); |
201 | rinfo->panel_info.fbk_divider = BIOS_IN16(tmp + 49); |
202 | if (rinfo->panel_info.ref_divider != 0 && |
203 | rinfo->panel_info.fbk_divider > 3) { |
204 | rinfo->panel_info.use_bios_dividers = 1; |
205 | printk(KERN_INFO "radeondb: BIOS provided dividers will be used\n" ); |
206 | pr_debug("ref_divider = %x\n" , rinfo->panel_info.ref_divider); |
207 | pr_debug("post_divider = %x\n" , rinfo->panel_info.post_divider); |
208 | pr_debug("fbk_divider = %x\n" , rinfo->panel_info.fbk_divider); |
209 | } |
210 | pr_debug("Scanning BIOS table ...\n" ); |
211 | for(i=0; i<32; i++) { |
212 | tmp0 = BIOS_IN16(tmp+64+i*2); |
213 | if (tmp0 == 0) |
214 | break; |
215 | pr_debug(" %d x %d\n" , BIOS_IN16(tmp0), BIOS_IN16(tmp0+2)); |
216 | if ((BIOS_IN16(tmp0) == rinfo->panel_info.xres) && |
217 | (BIOS_IN16(tmp0+2) == rinfo->panel_info.yres)) { |
218 | rinfo->panel_info.hblank = (BIOS_IN16(tmp0+17) - BIOS_IN16(tmp0+19)) * 8; |
219 | rinfo->panel_info.hOver_plus = ((BIOS_IN16(tmp0+21) - |
220 | BIOS_IN16(tmp0+19) -1) * 8) & 0x7fff; |
221 | rinfo->panel_info.hSync_width = BIOS_IN8(tmp0+23) * 8; |
222 | rinfo->panel_info.vblank = BIOS_IN16(tmp0+24) - BIOS_IN16(tmp0+26); |
223 | rinfo->panel_info.vOver_plus = (BIOS_IN16(tmp0+28) & 0x7ff) - BIOS_IN16(tmp0+26); |
224 | rinfo->panel_info.vSync_width = (BIOS_IN16(tmp0+28) & 0xf800) >> 11; |
225 | rinfo->panel_info.clock = BIOS_IN16(tmp0+9); |
226 | /* Assume high active syncs for now until ATI tells me more... maybe we |
227 | * can probe register values here ? |
228 | */ |
229 | rinfo->panel_info.hAct_high = 1; |
230 | rinfo->panel_info.vAct_high = 1; |
231 | /* Mark panel infos valid */ |
232 | rinfo->panel_info.valid = 1; |
233 | |
234 | pr_debug("Found panel in BIOS table:\n" ); |
235 | pr_debug(" hblank: %d\n" , rinfo->panel_info.hblank); |
236 | pr_debug(" hOver_plus: %d\n" , rinfo->panel_info.hOver_plus); |
237 | pr_debug(" hSync_width: %d\n" , rinfo->panel_info.hSync_width); |
238 | pr_debug(" vblank: %d\n" , rinfo->panel_info.vblank); |
239 | pr_debug(" vOver_plus: %d\n" , rinfo->panel_info.vOver_plus); |
240 | pr_debug(" vSync_width: %d\n" , rinfo->panel_info.vSync_width); |
241 | pr_debug(" clock: %d\n" , rinfo->panel_info.clock); |
242 | |
243 | return 1; |
244 | } |
245 | } |
246 | pr_debug("Didn't find panel in BIOS table !\n" ); |
247 | |
248 | return 0; |
249 | } |
250 | |
251 | /* Try to extract the connector informations from the BIOS. This |
252 | * doesn't quite work yet, but it's output is still useful for |
253 | * debugging |
254 | */ |
255 | static void radeon_parse_connector_info(struct radeonfb_info *rinfo) |
256 | { |
257 | int offset, chips, connectors, tmp, i, conn, type; |
258 | |
259 | static char* __conn_type_table[16] = { |
260 | "NONE" , "Proprietary" , "CRT" , "DVI-I" , "DVI-D" , "Unknown" , "Unknown" , |
261 | "Unknown" , "Unknown" , "Unknown" , "Unknown" , "Unknown" , "Unknown" , |
262 | "Unknown" , "Unknown" , "Unknown" |
263 | }; |
264 | |
265 | if (!rinfo->bios_seg) |
266 | return; |
267 | |
268 | offset = BIOS_IN16(rinfo->fp_bios_start + 0x50); |
269 | if (offset == 0) { |
270 | printk(KERN_WARNING "radeonfb: No connector info table detected\n" ); |
271 | return; |
272 | } |
273 | |
274 | /* Don't do much more at this point but displaying the data if |
275 | * DEBUG is enabled |
276 | */ |
277 | chips = BIOS_IN8(offset++) >> 4; |
278 | pr_debug("%d chips in connector info\n" , chips); |
279 | for (i = 0; i < chips; i++) { |
280 | tmp = BIOS_IN8(offset++); |
281 | connectors = tmp & 0x0f; |
282 | pr_debug(" - chip %d has %d connectors\n" , tmp >> 4, connectors); |
283 | for (conn = 0; ; conn++) { |
284 | tmp = BIOS_IN16(offset); |
285 | if (tmp == 0) |
286 | break; |
287 | offset += 2; |
288 | type = (tmp >> 12) & 0x0f; |
289 | pr_debug(" * connector %d of type %d (%s) : %04x\n" , |
290 | conn, type, __conn_type_table[type], tmp); |
291 | } |
292 | } |
293 | } |
294 | |
295 | |
296 | /* |
297 | * Probe physical connection of a CRT. This code comes from XFree |
298 | * as well and currently is only implemented for the CRT DAC, the |
299 | * code for the TVDAC is commented out in XFree as "non working" |
300 | */ |
301 | static int radeon_crt_is_connected(struct radeonfb_info *rinfo, int is_crt_dac) |
302 | { |
303 | int connected = 0; |
304 | |
305 | /* the monitor either wasn't connected or it is a non-DDC CRT. |
306 | * try to probe it |
307 | */ |
308 | if (is_crt_dac) { |
309 | unsigned long ulOrigVCLK_ECP_CNTL; |
310 | unsigned long ulOrigDAC_CNTL; |
311 | unsigned long ulOrigDAC_EXT_CNTL; |
312 | unsigned long ulOrigCRTC_EXT_CNTL; |
313 | unsigned long ulData; |
314 | unsigned long ulMask; |
315 | |
316 | ulOrigVCLK_ECP_CNTL = INPLL(VCLK_ECP_CNTL); |
317 | |
318 | ulData = ulOrigVCLK_ECP_CNTL; |
319 | ulData &= ~(PIXCLK_ALWAYS_ONb |
320 | | PIXCLK_DAC_ALWAYS_ONb); |
321 | ulMask = ~(PIXCLK_ALWAYS_ONb |
322 | | PIXCLK_DAC_ALWAYS_ONb); |
323 | OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask); |
324 | |
325 | ulOrigCRTC_EXT_CNTL = INREG(CRTC_EXT_CNTL); |
326 | ulData = ulOrigCRTC_EXT_CNTL; |
327 | ulData |= CRTC_CRT_ON; |
328 | OUTREG(CRTC_EXT_CNTL, ulData); |
329 | |
330 | ulOrigDAC_EXT_CNTL = INREG(DAC_EXT_CNTL); |
331 | ulData = ulOrigDAC_EXT_CNTL; |
332 | ulData &= ~DAC_FORCE_DATA_MASK; |
333 | ulData |= (DAC_FORCE_BLANK_OFF_EN |
334 | |DAC_FORCE_DATA_EN |
335 | |DAC_FORCE_DATA_SEL_MASK); |
336 | if ((rinfo->family == CHIP_FAMILY_RV250) || |
337 | (rinfo->family == CHIP_FAMILY_RV280)) |
338 | ulData |= (0x01b6 << DAC_FORCE_DATA_SHIFT); |
339 | else |
340 | ulData |= (0x01ac << DAC_FORCE_DATA_SHIFT); |
341 | |
342 | OUTREG(DAC_EXT_CNTL, ulData); |
343 | |
344 | ulOrigDAC_CNTL = INREG(DAC_CNTL); |
345 | ulData = ulOrigDAC_CNTL; |
346 | ulData |= DAC_CMP_EN; |
347 | ulData &= ~(DAC_RANGE_CNTL_MASK |
348 | | DAC_PDWN); |
349 | ulData |= 0x2; |
350 | OUTREG(DAC_CNTL, ulData); |
351 | |
352 | mdelay(1); |
353 | |
354 | ulData = INREG(DAC_CNTL); |
355 | connected = (DAC_CMP_OUTPUT & ulData) ? 1 : 0; |
356 | |
357 | ulData = ulOrigVCLK_ECP_CNTL; |
358 | ulMask = 0xFFFFFFFFL; |
359 | OUTPLLP(VCLK_ECP_CNTL, ulData, ulMask); |
360 | |
361 | OUTREG(DAC_CNTL, ulOrigDAC_CNTL ); |
362 | OUTREG(DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); |
363 | OUTREG(CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); |
364 | } |
365 | |
366 | return connected ? MT_CRT : MT_NONE; |
367 | } |
368 | |
369 | /* |
370 | * Parse the "monitor_layout" string if any. This code is mostly |
371 | * copied from XFree's radeon driver |
372 | */ |
373 | static int radeon_parse_monitor_layout(struct radeonfb_info *rinfo, |
374 | const char *monitor_layout) |
375 | { |
376 | char s1[5], s2[5]; |
377 | int i = 0, second = 0; |
378 | const char *s; |
379 | |
380 | if (!monitor_layout) |
381 | return 0; |
382 | |
383 | s = monitor_layout; |
384 | do { |
385 | switch(*s) { |
386 | case ',': |
387 | s1[i] = '\0'; |
388 | i = 0; |
389 | second = 1; |
390 | break; |
391 | case ' ': |
392 | case '\0': |
393 | break; |
394 | default: |
395 | if (i > 4) |
396 | break; |
397 | if (second) |
398 | s2[i] = *s; |
399 | else |
400 | s1[i] = *s; |
401 | i++; |
402 | } |
403 | |
404 | if (i > 4) |
405 | i = 4; |
406 | |
407 | } while (*s++); |
408 | if (second) |
409 | s2[i] = 0; |
410 | else { |
411 | s1[i] = 0; |
412 | s2[0] = 0; |
413 | } |
414 | if (strcmp(s1, "CRT" ) == 0) |
415 | rinfo->mon1_type = MT_CRT; |
416 | else if (strcmp(s1, "TMDS" ) == 0) |
417 | rinfo->mon1_type = MT_DFP; |
418 | else if (strcmp(s1, "LVDS" ) == 0) |
419 | rinfo->mon1_type = MT_LCD; |
420 | |
421 | if (strcmp(s2, "CRT" ) == 0) |
422 | rinfo->mon2_type = MT_CRT; |
423 | else if (strcmp(s2, "TMDS" ) == 0) |
424 | rinfo->mon2_type = MT_DFP; |
425 | else if (strcmp(s2, "LVDS" ) == 0) |
426 | rinfo->mon2_type = MT_LCD; |
427 | |
428 | return 1; |
429 | } |
430 | |
431 | /* |
432 | * Probe display on both primary and secondary card's connector (if any) |
433 | * by various available techniques (i2c, OF device tree, BIOS, ...) and |
434 | * try to retrieve EDID. The algorithm here comes from XFree's radeon |
435 | * driver |
436 | */ |
437 | void radeon_probe_screens(struct radeonfb_info *rinfo, |
438 | const char *monitor_layout, int ignore_edid) |
439 | { |
440 | #ifdef CONFIG_FB_RADEON_I2C |
441 | int ddc_crt2_used = 0; |
442 | #endif |
443 | int tmp, i; |
444 | |
445 | radeon_parse_connector_info(rinfo); |
446 | |
447 | if (radeon_parse_monitor_layout(rinfo, monitor_layout)) { |
448 | |
449 | /* |
450 | * If user specified a monitor_layout option, use it instead |
451 | * of auto-detecting. Maybe we should only use this argument |
452 | * on the first radeon card probed or provide a way to specify |
453 | * a layout for each card ? |
454 | */ |
455 | |
456 | pr_debug("Using specified monitor layout: %s" , monitor_layout); |
457 | #ifdef CONFIG_FB_RADEON_I2C |
458 | if (!ignore_edid) { |
459 | if (rinfo->mon1_type != MT_NONE) |
460 | if (!radeon_probe_i2c_connector(rinfo, conn: ddc_dvi, out_edid: &rinfo->mon1_EDID)) { |
461 | radeon_probe_i2c_connector(rinfo, conn: ddc_crt2, out_edid: &rinfo->mon1_EDID); |
462 | ddc_crt2_used = 1; |
463 | } |
464 | if (rinfo->mon2_type != MT_NONE) |
465 | if (!radeon_probe_i2c_connector(rinfo, conn: ddc_vga, out_edid: &rinfo->mon2_EDID) && |
466 | !ddc_crt2_used) |
467 | radeon_probe_i2c_connector(rinfo, conn: ddc_crt2, out_edid: &rinfo->mon2_EDID); |
468 | } |
469 | #endif /* CONFIG_FB_RADEON_I2C */ |
470 | if (rinfo->mon1_type == MT_NONE) { |
471 | if (rinfo->mon2_type != MT_NONE) { |
472 | rinfo->mon1_type = rinfo->mon2_type; |
473 | rinfo->mon1_EDID = rinfo->mon2_EDID; |
474 | } else { |
475 | rinfo->mon1_type = MT_CRT; |
476 | printk(KERN_INFO "radeonfb: No valid monitor, assuming CRT on first port\n" ); |
477 | } |
478 | rinfo->mon2_type = MT_NONE; |
479 | rinfo->mon2_EDID = NULL; |
480 | } |
481 | } else { |
482 | /* |
483 | * Auto-detecting display type (well... trying to ...) |
484 | */ |
485 | |
486 | pr_debug("Starting monitor auto detection...\n" ); |
487 | |
488 | #if defined(DEBUG) && defined(CONFIG_FB_RADEON_I2C) |
489 | { |
490 | u8 *EDIDs[4] = { NULL, NULL, NULL, NULL }; |
491 | int i; |
492 | |
493 | for (i = 0; i < 4; i++) |
494 | radeon_probe_i2c_connector(rinfo, conn: i + 1, out_edid: &EDIDs[i]); |
495 | } |
496 | #endif /* DEBUG */ |
497 | /* |
498 | * Old single head cards |
499 | */ |
500 | if (!rinfo->has_CRTC2) { |
501 | #if defined(CONFIG_PPC) || defined(CONFIG_SPARC) |
502 | if (rinfo->mon1_type == MT_NONE) |
503 | rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0, |
504 | &rinfo->mon1_EDID); |
505 | #endif /* CONFIG_PPC || CONFIG_SPARC */ |
506 | #ifdef CONFIG_FB_RADEON_I2C |
507 | if (rinfo->mon1_type == MT_NONE) |
508 | rinfo->mon1_type = |
509 | radeon_probe_i2c_connector(rinfo, conn: ddc_dvi, |
510 | out_edid: &rinfo->mon1_EDID); |
511 | if (rinfo->mon1_type == MT_NONE) |
512 | rinfo->mon1_type = |
513 | radeon_probe_i2c_connector(rinfo, conn: ddc_vga, |
514 | out_edid: &rinfo->mon1_EDID); |
515 | if (rinfo->mon1_type == MT_NONE) |
516 | rinfo->mon1_type = |
517 | radeon_probe_i2c_connector(rinfo, conn: ddc_crt2, |
518 | out_edid: &rinfo->mon1_EDID); |
519 | #endif /* CONFIG_FB_RADEON_I2C */ |
520 | if (rinfo->mon1_type == MT_NONE) |
521 | rinfo->mon1_type = MT_CRT; |
522 | goto bail; |
523 | } |
524 | |
525 | /* |
526 | * Check for cards with reversed DACs or TMDS controllers using BIOS |
527 | */ |
528 | if (rinfo->bios_seg && |
529 | (tmp = BIOS_IN16(rinfo->fp_bios_start + 0x50))) { |
530 | for (i = 1; i < 4; i++) { |
531 | unsigned int tmp0; |
532 | |
533 | if (!BIOS_IN8(tmp + i*2) && i > 1) |
534 | break; |
535 | tmp0 = BIOS_IN16(tmp + i*2); |
536 | if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0x0f) == ddc_dvi)) { |
537 | rinfo->reversed_DAC = 1; |
538 | printk(KERN_INFO "radeonfb: Reversed DACs detected\n" ); |
539 | } |
540 | if ((((tmp0 >> 8) & 0x0f) == ddc_dvi) && ((tmp0 >> 4) & 0x01)) { |
541 | rinfo->reversed_TMDS = 1; |
542 | printk(KERN_INFO "radeonfb: Reversed TMDS detected\n" ); |
543 | } |
544 | } |
545 | } |
546 | |
547 | /* |
548 | * Probe primary head (DVI or laptop internal panel) |
549 | */ |
550 | #if defined(CONFIG_PPC) || defined(CONFIG_SPARC) |
551 | if (rinfo->mon1_type == MT_NONE) |
552 | rinfo->mon1_type = radeon_probe_OF_head(rinfo, 0, |
553 | &rinfo->mon1_EDID); |
554 | #endif /* CONFIG_PPC || CONFIG_SPARC */ |
555 | #ifdef CONFIG_FB_RADEON_I2C |
556 | if (rinfo->mon1_type == MT_NONE) |
557 | rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, conn: ddc_dvi, |
558 | out_edid: &rinfo->mon1_EDID); |
559 | if (rinfo->mon1_type == MT_NONE) { |
560 | rinfo->mon1_type = radeon_probe_i2c_connector(rinfo, conn: ddc_crt2, |
561 | out_edid: &rinfo->mon1_EDID); |
562 | if (rinfo->mon1_type != MT_NONE) |
563 | ddc_crt2_used = 1; |
564 | } |
565 | #endif /* CONFIG_FB_RADEON_I2C */ |
566 | if (rinfo->mon1_type == MT_NONE && rinfo->is_mobility && |
567 | ((rinfo->bios_seg && (INREG(BIOS_4_SCRATCH) & 4)) |
568 | || (INREG(LVDS_GEN_CNTL) & LVDS_ON))) { |
569 | rinfo->mon1_type = MT_LCD; |
570 | printk("Non-DDC laptop panel detected\n" ); |
571 | } |
572 | if (rinfo->mon1_type == MT_NONE) |
573 | rinfo->mon1_type = radeon_crt_is_connected(rinfo, is_crt_dac: rinfo->reversed_DAC); |
574 | |
575 | /* |
576 | * Probe secondary head (mostly VGA, can be DVI) |
577 | */ |
578 | #if defined(CONFIG_PPC) || defined(CONFIG_SPARC) |
579 | if (rinfo->mon2_type == MT_NONE) |
580 | rinfo->mon2_type = radeon_probe_OF_head(rinfo, 1, |
581 | &rinfo->mon2_EDID); |
582 | #endif /* CONFIG_PPC || defined(CONFIG_SPARC) */ |
583 | #ifdef CONFIG_FB_RADEON_I2C |
584 | if (rinfo->mon2_type == MT_NONE) |
585 | rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, conn: ddc_vga, |
586 | out_edid: &rinfo->mon2_EDID); |
587 | if (rinfo->mon2_type == MT_NONE && !ddc_crt2_used) |
588 | rinfo->mon2_type = radeon_probe_i2c_connector(rinfo, conn: ddc_crt2, |
589 | out_edid: &rinfo->mon2_EDID); |
590 | #endif /* CONFIG_FB_RADEON_I2C */ |
591 | if (rinfo->mon2_type == MT_NONE) |
592 | rinfo->mon2_type = radeon_crt_is_connected(rinfo, is_crt_dac: !rinfo->reversed_DAC); |
593 | |
594 | /* |
595 | * If we only detected port 2, we swap them, if none detected, |
596 | * assume CRT (maybe fallback to old BIOS_SCRATCH stuff ? or look |
597 | * at FP registers ?) |
598 | */ |
599 | if (rinfo->mon1_type == MT_NONE) { |
600 | if (rinfo->mon2_type != MT_NONE) { |
601 | rinfo->mon1_type = rinfo->mon2_type; |
602 | rinfo->mon1_EDID = rinfo->mon2_EDID; |
603 | } else |
604 | rinfo->mon1_type = MT_CRT; |
605 | rinfo->mon2_type = MT_NONE; |
606 | rinfo->mon2_EDID = NULL; |
607 | } |
608 | |
609 | /* |
610 | * Deal with reversed TMDS |
611 | */ |
612 | if (rinfo->reversed_TMDS) { |
613 | /* Always keep internal TMDS as primary head */ |
614 | if (rinfo->mon1_type == MT_DFP || rinfo->mon2_type == MT_DFP) { |
615 | int tmp_type = rinfo->mon1_type; |
616 | u8 *tmp_EDID = rinfo->mon1_EDID; |
617 | rinfo->mon1_type = rinfo->mon2_type; |
618 | rinfo->mon1_EDID = rinfo->mon2_EDID; |
619 | rinfo->mon2_type = tmp_type; |
620 | rinfo->mon2_EDID = tmp_EDID; |
621 | if (rinfo->mon1_type == MT_CRT || rinfo->mon2_type == MT_CRT) |
622 | rinfo->reversed_DAC ^= 1; |
623 | } |
624 | } |
625 | } |
626 | if (ignore_edid) { |
627 | kfree(objp: rinfo->mon1_EDID); |
628 | rinfo->mon1_EDID = NULL; |
629 | kfree(objp: rinfo->mon2_EDID); |
630 | rinfo->mon2_EDID = NULL; |
631 | } |
632 | |
633 | bail: |
634 | printk(KERN_INFO "radeonfb: Monitor 1 type %s found\n" , |
635 | radeon_get_mon_name(rinfo->mon1_type)); |
636 | if (rinfo->mon1_EDID) |
637 | printk(KERN_INFO "radeonfb: EDID probed\n" ); |
638 | if (!rinfo->has_CRTC2) |
639 | return; |
640 | printk(KERN_INFO "radeonfb: Monitor 2 type %s found\n" , |
641 | radeon_get_mon_name(rinfo->mon2_type)); |
642 | if (rinfo->mon2_EDID) |
643 | printk(KERN_INFO "radeonfb: EDID probed\n" ); |
644 | } |
645 | |
646 | |
647 | /* |
648 | * This function applies any arch/model/machine specific fixups |
649 | * to the panel info. It may eventually alter EDID block as |
650 | * well or whatever is specific to a given model and not probed |
651 | * properly by the default code |
652 | */ |
653 | static void radeon_fixup_panel_info(struct radeonfb_info *rinfo) |
654 | { |
655 | #ifdef CONFIG_PPC |
656 | /* |
657 | * LCD Flat panels should use fixed dividers, we enfore that on |
658 | * PPC only for now... |
659 | */ |
660 | if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD |
661 | && rinfo->is_mobility) { |
662 | int ppll_div_sel; |
663 | u32 ppll_divn; |
664 | ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3; |
665 | radeon_pll_errata_after_index(rinfo); |
666 | ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel); |
667 | rinfo->panel_info.ref_divider = rinfo->pll.ref_div; |
668 | rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff; |
669 | rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7; |
670 | rinfo->panel_info.use_bios_dividers = 1; |
671 | |
672 | printk(KERN_DEBUG "radeonfb: Using Firmware dividers 0x%08x " |
673 | "from PPLL %d\n" , |
674 | rinfo->panel_info.fbk_divider | |
675 | (rinfo->panel_info.post_divider << 16), |
676 | ppll_div_sel); |
677 | } |
678 | #endif /* CONFIG_PPC */ |
679 | } |
680 | |
681 | |
682 | /* |
683 | * Fill up panel infos from a mode definition, either returned by the EDID |
684 | * or from the default mode when we can't do any better |
685 | */ |
686 | static void radeon_var_to_panel_info(struct radeonfb_info *rinfo, struct fb_var_screeninfo *var) |
687 | { |
688 | rinfo->panel_info.xres = var->xres; |
689 | rinfo->panel_info.yres = var->yres; |
690 | rinfo->panel_info.clock = 100000000 / var->pixclock; |
691 | rinfo->panel_info.hOver_plus = var->right_margin; |
692 | rinfo->panel_info.hSync_width = var->hsync_len; |
693 | rinfo->panel_info.hblank = var->left_margin + |
694 | (var->right_margin + var->hsync_len); |
695 | rinfo->panel_info.vOver_plus = var->lower_margin; |
696 | rinfo->panel_info.vSync_width = var->vsync_len; |
697 | rinfo->panel_info.vblank = var->upper_margin + |
698 | (var->lower_margin + var->vsync_len); |
699 | rinfo->panel_info.hAct_high = |
700 | (var->sync & FB_SYNC_HOR_HIGH_ACT) != 0; |
701 | rinfo->panel_info.vAct_high = |
702 | (var->sync & FB_SYNC_VERT_HIGH_ACT) != 0; |
703 | rinfo->panel_info.valid = 1; |
704 | /* We use a default of 200ms for the panel power delay, |
705 | * I need to have a real schedule() instead of mdelay's in the panel code. |
706 | * we might be possible to figure out a better power delay either from |
707 | * MacOS OF tree or from the EDID block (proprietary extensions ?) |
708 | */ |
709 | rinfo->panel_info.pwr_delay = 200; |
710 | } |
711 | |
712 | static void radeon_videomode_to_var(struct fb_var_screeninfo *var, |
713 | const struct fb_videomode *mode) |
714 | { |
715 | var->xres = mode->xres; |
716 | var->yres = mode->yres; |
717 | var->xres_virtual = mode->xres; |
718 | var->yres_virtual = mode->yres; |
719 | var->xoffset = 0; |
720 | var->yoffset = 0; |
721 | var->pixclock = mode->pixclock; |
722 | var->left_margin = mode->left_margin; |
723 | var->right_margin = mode->right_margin; |
724 | var->upper_margin = mode->upper_margin; |
725 | var->lower_margin = mode->lower_margin; |
726 | var->hsync_len = mode->hsync_len; |
727 | var->vsync_len = mode->vsync_len; |
728 | var->sync = mode->sync; |
729 | var->vmode = mode->vmode; |
730 | } |
731 | |
732 | #ifdef CONFIG_PPC_PSERIES |
733 | static int is_powerblade(const char *model) |
734 | { |
735 | struct device_node *root; |
736 | const char* cp; |
737 | int len, l, rc = 0; |
738 | |
739 | root = of_find_node_by_path("/" ); |
740 | if (root && model) { |
741 | l = strlen(model); |
742 | cp = of_get_property(root, "model" , &len); |
743 | if (cp) |
744 | rc = memcmp(model, cp, min(len, l)) == 0; |
745 | of_node_put(root); |
746 | } |
747 | return rc; |
748 | } |
749 | #endif |
750 | |
751 | /* |
752 | * Build the modedb for head 1 (head 2 will come later), check panel infos |
753 | * from either BIOS or EDID, and pick up the default mode |
754 | */ |
755 | void radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_option) |
756 | { |
757 | struct fb_info * info = rinfo->info; |
758 | int has_default_mode = 0; |
759 | |
760 | /* |
761 | * Fill default var first |
762 | */ |
763 | info->var = radeonfb_default_var; |
764 | INIT_LIST_HEAD(list: &info->modelist); |
765 | |
766 | /* |
767 | * First check out what BIOS has to say |
768 | */ |
769 | if (rinfo->mon1_type == MT_LCD) |
770 | radeon_get_panel_info_BIOS(rinfo); |
771 | |
772 | /* |
773 | * Parse EDID detailed timings and deduce panel infos if any. Right now |
774 | * we only deal with first entry returned by parse_EDID, we may do better |
775 | * some day... |
776 | */ |
777 | if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type != MT_CRT |
778 | && rinfo->mon1_EDID) { |
779 | struct fb_var_screeninfo var; |
780 | pr_debug("Parsing EDID data for panel info\n" ); |
781 | if (fb_parse_edid(edid: rinfo->mon1_EDID, var: &var) == 0) { |
782 | if (var.xres >= rinfo->panel_info.xres && |
783 | var.yres >= rinfo->panel_info.yres) |
784 | radeon_var_to_panel_info(rinfo, var: &var); |
785 | } |
786 | } |
787 | |
788 | /* |
789 | * Do any additional platform/arch fixups to the panel infos |
790 | */ |
791 | radeon_fixup_panel_info(rinfo); |
792 | |
793 | /* |
794 | * If we have some valid panel infos, we setup the default mode based on |
795 | * those |
796 | */ |
797 | if (rinfo->mon1_type != MT_CRT && rinfo->panel_info.valid) { |
798 | struct fb_var_screeninfo *var = &info->var; |
799 | |
800 | pr_debug("Setting up default mode based on panel info\n" ); |
801 | var->xres = rinfo->panel_info.xres; |
802 | var->yres = rinfo->panel_info.yres; |
803 | var->xres_virtual = rinfo->panel_info.xres; |
804 | var->yres_virtual = rinfo->panel_info.yres; |
805 | var->xoffset = var->yoffset = 0; |
806 | var->bits_per_pixel = 8; |
807 | var->pixclock = 100000000 / rinfo->panel_info.clock; |
808 | var->left_margin = (rinfo->panel_info.hblank - rinfo->panel_info.hOver_plus |
809 | - rinfo->panel_info.hSync_width); |
810 | var->right_margin = rinfo->panel_info.hOver_plus; |
811 | var->upper_margin = (rinfo->panel_info.vblank - rinfo->panel_info.vOver_plus |
812 | - rinfo->panel_info.vSync_width); |
813 | var->lower_margin = rinfo->panel_info.vOver_plus; |
814 | var->hsync_len = rinfo->panel_info.hSync_width; |
815 | var->vsync_len = rinfo->panel_info.vSync_width; |
816 | var->sync = 0; |
817 | if (rinfo->panel_info.hAct_high) |
818 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
819 | if (rinfo->panel_info.vAct_high) |
820 | var->sync |= FB_SYNC_VERT_HIGH_ACT; |
821 | var->vmode = 0; |
822 | has_default_mode = 1; |
823 | } |
824 | |
825 | /* |
826 | * Now build modedb from EDID |
827 | */ |
828 | if (rinfo->mon1_EDID) { |
829 | fb_edid_to_monspecs(edid: rinfo->mon1_EDID, specs: &info->monspecs); |
830 | fb_videomode_to_modelist(modedb: info->monspecs.modedb, |
831 | num: info->monspecs.modedb_len, |
832 | head: &info->modelist); |
833 | rinfo->mon1_modedb = info->monspecs.modedb; |
834 | rinfo->mon1_dbsize = info->monspecs.modedb_len; |
835 | } |
836 | |
837 | |
838 | /* |
839 | * Finally, if we don't have panel infos we need to figure some (or |
840 | * we try to read it from card), we try to pick a default mode |
841 | * and create some panel infos. Whatever... |
842 | */ |
843 | if (rinfo->mon1_type != MT_CRT && !rinfo->panel_info.valid) { |
844 | struct fb_videomode *modedb; |
845 | int dbsize; |
846 | char modename[32]; |
847 | |
848 | pr_debug("Guessing panel info...\n" ); |
849 | if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) { |
850 | u32 tmp = INREG(FP_HORZ_STRETCH) & HORZ_PANEL_SIZE; |
851 | rinfo->panel_info.xres = ((tmp >> HORZ_PANEL_SHIFT) + 1) * 8; |
852 | tmp = INREG(FP_VERT_STRETCH) & VERT_PANEL_SIZE; |
853 | rinfo->panel_info.yres = (tmp >> VERT_PANEL_SHIFT) + 1; |
854 | } |
855 | if (rinfo->panel_info.xres == 0 || rinfo->panel_info.yres == 0) { |
856 | printk(KERN_WARNING "radeonfb: Can't find panel size, going back to CRT\n" ); |
857 | rinfo->mon1_type = MT_CRT; |
858 | goto pickup_default; |
859 | } |
860 | printk(KERN_WARNING "radeonfb: Assuming panel size %dx%d\n" , |
861 | rinfo->panel_info.xres, rinfo->panel_info.yres); |
862 | modedb = rinfo->mon1_modedb; |
863 | dbsize = rinfo->mon1_dbsize; |
864 | snprintf(buf: modename, size: 31, fmt: "%dx%d" , rinfo->panel_info.xres, rinfo->panel_info.yres); |
865 | if (fb_find_mode(var: &info->var, info, mode_option: modename, |
866 | db: modedb, dbsize, NULL, default_bpp: 8) == 0) { |
867 | printk(KERN_WARNING "radeonfb: Can't find mode for panel size, going back to CRT\n" ); |
868 | rinfo->mon1_type = MT_CRT; |
869 | goto pickup_default; |
870 | } |
871 | has_default_mode = 1; |
872 | radeon_var_to_panel_info(rinfo, var: &info->var); |
873 | } |
874 | |
875 | pickup_default: |
876 | /* |
877 | * Apply passed-in mode option if any |
878 | */ |
879 | if (mode_option) { |
880 | if (fb_find_mode(var: &info->var, info, mode_option, |
881 | db: info->monspecs.modedb, |
882 | dbsize: info->monspecs.modedb_len, NULL, default_bpp: 8) != 0) |
883 | has_default_mode = 1; |
884 | } |
885 | |
886 | #ifdef CONFIG_PPC_PSERIES |
887 | if (!has_default_mode && ( |
888 | is_powerblade("IBM,8842" ) || /* JS20 */ |
889 | is_powerblade("IBM,8844" ) || /* JS21 */ |
890 | is_powerblade("IBM,7998" ) || /* JS12/JS21/JS22 */ |
891 | is_powerblade("IBM,0792" ) || /* QS21 */ |
892 | is_powerblade("IBM,0793" ) /* QS22 */ |
893 | )) { |
894 | printk("Falling back to 800x600 on JSxx hardware\n" ); |
895 | if (fb_find_mode(&info->var, info, "800x600@60" , |
896 | info->monspecs.modedb, |
897 | info->monspecs.modedb_len, NULL, 8) != 0) |
898 | has_default_mode = 1; |
899 | } |
900 | #endif |
901 | |
902 | /* |
903 | * Still no mode, let's pick up a default from the db |
904 | */ |
905 | if (!has_default_mode && info->monspecs.modedb != NULL) { |
906 | struct fb_monspecs *specs = &info->monspecs; |
907 | struct fb_videomode *modedb = NULL; |
908 | |
909 | /* get preferred timing */ |
910 | if (specs->misc & FB_MISC_1ST_DETAIL) { |
911 | int i; |
912 | |
913 | for (i = 0; i < specs->modedb_len; i++) { |
914 | if (specs->modedb[i].flag & FB_MODE_IS_FIRST) { |
915 | modedb = &specs->modedb[i]; |
916 | break; |
917 | } |
918 | } |
919 | } else { |
920 | /* otherwise, get first mode in database */ |
921 | modedb = &specs->modedb[0]; |
922 | } |
923 | if (modedb != NULL) { |
924 | info->var.bits_per_pixel = 8; |
925 | radeon_videomode_to_var(var: &info->var, mode: modedb); |
926 | has_default_mode = 1; |
927 | } |
928 | } |
929 | if (1) { |
930 | struct fb_videomode mode; |
931 | /* Make sure that whatever mode got selected is actually in the |
932 | * modelist or the kernel may die |
933 | */ |
934 | fb_var_to_videomode(mode: &mode, var: &info->var); |
935 | fb_add_videomode(mode: &mode, head: &info->modelist); |
936 | } |
937 | } |
938 | |
939 | /* |
940 | * The code below is used to pick up a mode in check_var and |
941 | * set_var. It should be made generic |
942 | */ |
943 | |
944 | /* |
945 | * This is used when looking for modes. We assign a "distance" value |
946 | * to a mode in the modedb depending how "close" it is from what we |
947 | * are looking for. |
948 | * Currently, we don't compare that much, we could do better but |
949 | * the current fbcon doesn't quite mind ;) |
950 | */ |
951 | static int radeon_compare_modes(const struct fb_var_screeninfo *var, |
952 | const struct fb_videomode *mode) |
953 | { |
954 | int distance = 0; |
955 | |
956 | distance = mode->yres - var->yres; |
957 | distance += (mode->xres - var->xres)/2; |
958 | return distance; |
959 | } |
960 | |
961 | /* |
962 | * This function is called by check_var, it gets the passed in mode parameter, and |
963 | * outputs a valid mode matching the passed-in one as closely as possible. |
964 | * We need something better ultimately. Things like fbcon basically pass us out |
965 | * current mode with xres/yres hacked, while things like XFree will actually |
966 | * produce a full timing that we should respect as much as possible. |
967 | * |
968 | * This is why I added the FB_ACTIVATE_FIND that is used by fbcon. Without this, |
969 | * we do a simple spec match, that's all. With it, we actually look for a mode in |
970 | * either our monitor modedb or the vesa one if none |
971 | * |
972 | */ |
973 | int radeon_match_mode(struct radeonfb_info *rinfo, |
974 | struct fb_var_screeninfo *dest, |
975 | const struct fb_var_screeninfo *src) |
976 | { |
977 | const struct fb_videomode *db = vesa_modes; |
978 | int i, dbsize = 34; |
979 | int has_rmx, native_db = 0; |
980 | int distance = INT_MAX; |
981 | const struct fb_videomode *candidate = NULL; |
982 | |
983 | /* Start with a copy of the requested mode */ |
984 | memcpy(dest, src, sizeof(struct fb_var_screeninfo)); |
985 | |
986 | /* Check if we have a modedb built from EDID */ |
987 | if (rinfo->mon1_modedb) { |
988 | db = rinfo->mon1_modedb; |
989 | dbsize = rinfo->mon1_dbsize; |
990 | native_db = 1; |
991 | } |
992 | |
993 | /* Check if we have a scaler allowing any fancy mode */ |
994 | has_rmx = rinfo->mon1_type == MT_LCD || rinfo->mon1_type == MT_DFP; |
995 | |
996 | /* If we have a scaler and are passed FB_ACTIVATE_TEST or |
997 | * FB_ACTIVATE_NOW, just do basic checking and return if the |
998 | * mode match |
999 | */ |
1000 | if ((src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST || |
1001 | (src->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { |
1002 | /* We don't have an RMX, validate timings. If we don't have |
1003 | * monspecs, we should be paranoid and not let use go above |
1004 | * 640x480-60, but I assume userland knows what it's doing here |
1005 | * (though I may be proven wrong...) |
1006 | */ |
1007 | if (has_rmx == 0 && rinfo->mon1_modedb) |
1008 | if (fb_validate_mode(var: (struct fb_var_screeninfo *)src, info: rinfo->info)) |
1009 | return -EINVAL; |
1010 | return 0; |
1011 | } |
1012 | |
1013 | /* Now look for a mode in the database */ |
1014 | while (db) { |
1015 | for (i = 0; i < dbsize; i++) { |
1016 | int d; |
1017 | |
1018 | if (db[i].yres < src->yres) |
1019 | continue; |
1020 | if (db[i].xres < src->xres) |
1021 | continue; |
1022 | d = radeon_compare_modes(var: src, mode: &db[i]); |
1023 | /* If the new mode is at least as good as the previous one, |
1024 | * then it's our new candidate |
1025 | */ |
1026 | if (d < distance) { |
1027 | candidate = &db[i]; |
1028 | distance = d; |
1029 | } |
1030 | } |
1031 | db = NULL; |
1032 | /* If we have a scaler, we allow any mode from the database */ |
1033 | if (native_db && has_rmx) { |
1034 | db = vesa_modes; |
1035 | dbsize = 34; |
1036 | native_db = 0; |
1037 | } |
1038 | } |
1039 | |
1040 | /* If we have found a match, return it */ |
1041 | if (candidate != NULL) { |
1042 | radeon_videomode_to_var(var: dest, mode: candidate); |
1043 | return 0; |
1044 | } |
1045 | |
1046 | /* If we haven't and don't have a scaler, fail */ |
1047 | if (!has_rmx) |
1048 | return -EINVAL; |
1049 | |
1050 | return 0; |
1051 | } |
1052 | |