aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-12-15 19:46:45 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 10:20:05 -0500
commitcfbd646fe060f70fe6618be2f9c25f739c067e29 (patch)
tree7a5e55e8929bd221fde11baf2637fa8bae689546
parente6bf0d2c9a7f1b9b0ac77698017f8f06f9cc0317 (diff)
intelfb: fix setting of active pipe with LVDS displays
The intelfb driver sets color map depending on currently active pipe. However, if an LVDS display is attached (like in laptop) the active pipe variable is never set. The default value is PIPE_A and can be wrong. Set up the pipe variable during driver initialization after hardware state was read. Also, the detection of the active display (and hence the pipe) is wrong. The pipes are assigned to so called planes. Both pipes are always enabled on my laptop but only one plane is enabled (the plane A for the CRT or the plane B for the LVDS). Change active pipe detection code to take into account a status of the plane assigned to each pipe. The problem is visible in the 8 bpp mode if colors above 15 are used. The first 16 color entries are displayed correctly. The graphics chip description is here (G45 vol. 3): http://intellinuxgraphics.org/documentation.html Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13285 Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Cc: Michal Suchanek <hramrach@centrum.cz> Cc: Dean Menezes <samanddeanus@yahoo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/intelfb/intelfbdrv.c3
-rw-r--r--drivers/video/intelfb/intelfbhw.c47
-rw-r--r--drivers/video/intelfb/intelfbhw.h1
3 files changed, 34 insertions, 17 deletions
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 0cafd642fbc0..5ba399991050 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -874,6 +874,9 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
874 if (bailearly == 18) 874 if (bailearly == 18)
875 bailout(dinfo); 875 bailout(dinfo);
876 876
877 /* read active pipe */
878 dinfo->pipe = intelfbhw_active_pipe(&dinfo->save_state);
879
877 /* Cursor initialisation */ 880 /* Cursor initialisation */
878 if (dinfo->hwcursor) { 881 if (dinfo->hwcursor) {
879 intelfbhw_cursor_init(dinfo); 882 intelfbhw_cursor_init(dinfo);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 0689f97c5238..81627466804e 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -469,6 +469,32 @@ void intelfbhw_do_blank(int blank, struct fb_info *info)
469} 469}
470 470
471 471
472/* Check which pipe is connected to an active display plane. */
473int intelfbhw_active_pipe(const struct intelfb_hwstate *hw)
474{
475 int pipe = -1;
476
477 /* keep old default behaviour - prefer PIPE_A */
478 if (hw->disp_b_ctrl & DISPPLANE_PLANE_ENABLE) {
479 pipe = (hw->disp_b_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
480 pipe &= PIPE_MASK;
481 if (unlikely(pipe == PIPE_A))
482 return PIPE_A;
483 }
484 if (hw->disp_a_ctrl & DISPPLANE_PLANE_ENABLE) {
485 pipe = (hw->disp_a_ctrl >> DISPPLANE_SEL_PIPE_SHIFT);
486 pipe &= PIPE_MASK;
487 if (likely(pipe == PIPE_A))
488 return PIPE_A;
489 }
490 /* Impossible that no pipe is selected - return PIPE_A */
491 WARN_ON(pipe == -1);
492 if (unlikely(pipe == -1))
493 pipe = PIPE_A;
494
495 return pipe;
496}
497
472void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno, 498void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
473 unsigned red, unsigned green, unsigned blue, 499 unsigned red, unsigned green, unsigned blue,
474 unsigned transp) 500 unsigned transp)
@@ -1019,7 +1045,7 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1019 struct intelfb_hwstate *hw, 1045 struct intelfb_hwstate *hw,
1020 struct fb_var_screeninfo *var) 1046 struct fb_var_screeninfo *var)
1021{ 1047{
1022 int pipe = PIPE_A; 1048 int pipe = intelfbhw_active_pipe(hw);
1023 u32 *dpll, *fp0, *fp1; 1049 u32 *dpll, *fp0, *fp1;
1024 u32 m1, m2, n, p1, p2, clock_target, clock; 1050 u32 m1, m2, n, p1, p2, clock_target, clock;
1025 u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive; 1051 u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
@@ -1033,12 +1059,6 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1033 /* Disable VGA */ 1059 /* Disable VGA */
1034 hw->vgacntrl |= VGA_DISABLE; 1060 hw->vgacntrl |= VGA_DISABLE;
1035 1061
1036 /* Check whether pipe A or pipe B is enabled. */
1037 if (hw->pipe_a_conf & PIPECONF_ENABLE)
1038 pipe = PIPE_A;
1039 else if (hw->pipe_b_conf & PIPECONF_ENABLE)
1040 pipe = PIPE_B;
1041
1042 /* Set which pipe's registers will be set. */ 1062 /* Set which pipe's registers will be set. */
1043 if (pipe == PIPE_B) { 1063 if (pipe == PIPE_B) {
1044 dpll = &hw->dpll_b; 1064 dpll = &hw->dpll_b;
@@ -1262,7 +1282,6 @@ int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
1262int intelfbhw_program_mode(struct intelfb_info *dinfo, 1282int intelfbhw_program_mode(struct intelfb_info *dinfo,
1263 const struct intelfb_hwstate *hw, int blank) 1283 const struct intelfb_hwstate *hw, int blank)
1264{ 1284{
1265 int pipe = PIPE_A;
1266 u32 tmp; 1285 u32 tmp;
1267 const u32 *dpll, *fp0, *fp1, *pipe_conf; 1286 const u32 *dpll, *fp0, *fp1, *pipe_conf;
1268 const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss; 1287 const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
@@ -1272,7 +1291,7 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo,
1272 u32 src_size_reg; 1291 u32 src_size_reg;
1273 u32 count, tmp_val[3]; 1292 u32 count, tmp_val[3];
1274 1293
1275 /* Assume single pipe, display plane A, analog CRT. */ 1294 /* Assume single pipe */
1276 1295
1277#if VERBOSE > 0 1296#if VERBOSE > 0
1278 DBG_MSG("intelfbhw_program_mode\n"); 1297 DBG_MSG("intelfbhw_program_mode\n");
@@ -1283,15 +1302,9 @@ int intelfbhw_program_mode(struct intelfb_info *dinfo,
1283 tmp |= VGA_DISABLE; 1302 tmp |= VGA_DISABLE;
1284 OUTREG(VGACNTRL, tmp); 1303 OUTREG(VGACNTRL, tmp);
1285 1304
1286 /* Check whether pipe A or pipe B is enabled. */ 1305 dinfo->pipe = intelfbhw_active_pipe(hw);
1287 if (hw->pipe_a_conf & PIPECONF_ENABLE)
1288 pipe = PIPE_A;
1289 else if (hw->pipe_b_conf & PIPECONF_ENABLE)
1290 pipe = PIPE_B;
1291
1292 dinfo->pipe = pipe;
1293 1306
1294 if (pipe == PIPE_B) { 1307 if (dinfo->pipe == PIPE_B) {
1295 dpll = &hw->dpll_b; 1308 dpll = &hw->dpll_b;
1296 fp0 = &hw->fpb0; 1309 fp0 = &hw->fpb0;
1297 fp1 = &hw->fpb1; 1310 fp1 = &hw->fpb1;
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index 0b076bac321b..216ca20f259f 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -604,5 +604,6 @@ extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
604extern int intelfbhw_enable_irq(struct intelfb_info *dinfo); 604extern int intelfbhw_enable_irq(struct intelfb_info *dinfo);
605extern void intelfbhw_disable_irq(struct intelfb_info *dinfo); 605extern void intelfbhw_disable_irq(struct intelfb_info *dinfo);
606extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe); 606extern int intelfbhw_wait_for_vsync(struct intelfb_info *dinfo, u32 pipe);
607extern int intelfbhw_active_pipe(const struct intelfb_hwstate *hw);
607 608
608#endif /* _INTELFBHW_H */ 609#endif /* _INTELFBHW_H */