aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/udlfb.c97
-rw-r--r--include/video/udlfb.h1
2 files changed, 74 insertions, 24 deletions
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 087fc9960bb..fecd2d3543b 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -94,17 +94,39 @@ static char *dlfb_vidreg_unlock(char *buf)
94} 94}
95 95
96/* 96/*
97 * On/Off for driving the DisplayLink framebuffer to the display 97 * Map FB_BLANK_* to DisplayLink register
98 * 0x00 H and V sync on 98 * DLReg FB_BLANK_*
99 * 0x01 H and V sync off (screen blank but powered) 99 * ----- -----------------------------
100 * 0x07 DPMS powerdown (requires modeset to come back) 100 * 0x00 FB_BLANK_UNBLANK (0)
101 * 0x01 FB_BLANK (1)
102 * 0x03 FB_BLANK_VSYNC_SUSPEND (2)
103 * 0x05 FB_BLANK_HSYNC_SUSPEND (3)
104 * 0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back
101 */ 105 */
102static char *dlfb_enable_hvsync(char *buf, bool enable) 106static char *dlfb_blanking(char *buf, int fb_blank)
103{ 107{
104 if (enable) 108 u8 reg;
105 return dlfb_set_register(buf, 0x1F, 0x00); 109
106 else 110 switch (fb_blank) {
107 return dlfb_set_register(buf, 0x1F, 0x07); 111 case FB_BLANK_POWERDOWN:
112 reg = 0x07;
113 break;
114 case FB_BLANK_HSYNC_SUSPEND:
115 reg = 0x05;
116 break;
117 case FB_BLANK_VSYNC_SUSPEND:
118 reg = 0x03;
119 break;
120 case FB_BLANK_NORMAL:
121 reg = 0x01;
122 break;
123 default:
124 reg = 0x00;
125 }
126
127 buf = dlfb_set_register(buf, 0x1F, reg);
128
129 return buf;
108} 130}
109 131
110static char *dlfb_set_color_depth(char *buf, u8 selection) 132static char *dlfb_set_color_depth(char *buf, u8 selection)
@@ -272,13 +294,15 @@ static int dlfb_set_video_mode(struct dlfb_data *dev,
272 wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len); 294 wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
273 295
274 wrptr = dlfb_set_vid_cmds(wrptr, var); 296 wrptr = dlfb_set_vid_cmds(wrptr, var);
275 wrptr = dlfb_enable_hvsync(wrptr, true); 297 wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK);
276 wrptr = dlfb_vidreg_unlock(wrptr); 298 wrptr = dlfb_vidreg_unlock(wrptr);
277 299
278 writesize = wrptr - buf; 300 writesize = wrptr - buf;
279 301
280 retval = dlfb_submit_urb(dev, urb, writesize); 302 retval = dlfb_submit_urb(dev, urb, writesize);
281 303
304 dev->blank_mode = FB_BLANK_UNBLANK;
305
282 return retval; 306 return retval;
283} 307}
284 308
@@ -1039,32 +1063,57 @@ static int dlfb_ops_set_par(struct fb_info *info)
1039 return result; 1063 return result;
1040} 1064}
1041 1065
1066/* To fonzi the jukebox (e.g. make blanking changes take effect) */
1067static char *dlfb_dummy_render(char *buf)
1068{
1069 *buf++ = 0xAF;
1070 *buf++ = 0x6A; /* copy */
1071 *buf++ = 0x00; /* from address*/
1072 *buf++ = 0x00;
1073 *buf++ = 0x00;
1074 *buf++ = 0x01; /* one pixel */
1075 *buf++ = 0x00; /* to address */
1076 *buf++ = 0x00;
1077 *buf++ = 0x00;
1078 return buf;
1079}
1080
1042/* 1081/*
1043 * In order to come back from full DPMS off, we need to set the mode again 1082 * In order to come back from full DPMS off, we need to set the mode again
1044 */ 1083 */
1045static int dlfb_ops_blank(int blank_mode, struct fb_info *info) 1084static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
1046{ 1085{
1047 struct dlfb_data *dev = info->par; 1086 struct dlfb_data *dev = info->par;
1087 char *bufptr;
1088 struct urb *urb;
1048 1089
1049 if (blank_mode != FB_BLANK_UNBLANK) { 1090 pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n",
1050 char *bufptr; 1091 info->node, dev->blank_mode, blank_mode);
1051 struct urb *urb;
1052
1053 urb = dlfb_get_urb(dev);
1054 if (!urb)
1055 return 0;
1056 1092
1057 bufptr = (char *) urb->transfer_buffer; 1093 if ((dev->blank_mode == FB_BLANK_POWERDOWN) &&
1058 bufptr = dlfb_vidreg_lock(bufptr); 1094 (blank_mode != FB_BLANK_POWERDOWN)) {
1059 bufptr = dlfb_enable_hvsync(bufptr, false);
1060 bufptr = dlfb_vidreg_unlock(bufptr);
1061 1095
1062 dlfb_submit_urb(dev, urb, bufptr - 1096 /* returning from powerdown requires a fresh modeset */
1063 (char *) urb->transfer_buffer);
1064 } else {
1065 dlfb_set_video_mode(dev, &info->var); 1097 dlfb_set_video_mode(dev, &info->var);
1066 } 1098 }
1067 1099
1100 urb = dlfb_get_urb(dev);
1101 if (!urb)
1102 return 0;
1103
1104 bufptr = (char *) urb->transfer_buffer;
1105 bufptr = dlfb_vidreg_lock(bufptr);
1106 bufptr = dlfb_blanking(bufptr, blank_mode);
1107 bufptr = dlfb_vidreg_unlock(bufptr);
1108
1109 /* seems like a render op is needed to have blank change take effect */
1110 bufptr = dlfb_dummy_render(bufptr);
1111
1112 dlfb_submit_urb(dev, urb, bufptr -
1113 (char *) urb->transfer_buffer);
1114
1115 dev->blank_mode = blank_mode;
1116
1068 return 0; 1117 return 0;
1069} 1118}
1070 1119
diff --git a/include/video/udlfb.h b/include/video/udlfb.h
index 69d485a4a02..c41f308c963 100644
--- a/include/video/udlfb.h
+++ b/include/video/udlfb.h
@@ -50,6 +50,7 @@ struct dlfb_data {
50 int base16; 50 int base16;
51 int base8; 51 int base8;
52 u32 pseudo_palette[256]; 52 u32 pseudo_palette[256];
53 int blank_mode; /*one of FB_BLANK_ */
53 /* blit-only rendering path metrics, exposed through sysfs */ 54 /* blit-only rendering path metrics, exposed through sysfs */
54 atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */ 55 atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
55 atomic_t bytes_identical; /* saved effort with backbuffer comparison */ 56 atomic_t bytes_identical; /* saved effort with backbuffer comparison */