aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2018-06-03 10:40:54 -0400
committerDave Airlie <airlied@redhat.com>2018-07-05 02:44:51 -0400
commit99ec9e77511dea55d81729fc80b6c63a61bfa8e0 (patch)
tree0033c58a0538048119e07b91da637394fd25a0de
parent021c91791a5e7e85c567452f1be3e4c2c6cb6063 (diff)
drm/udl: fix display corruption of the last line
The displaylink hardware has such a peculiarity that it doesn't render a command until next command is received. This produces occasional corruption, such as when setting 22x11 font on the console, only the first line of the cursor will be blinking if the cursor is located at some specific columns. When we end up with a repeating pixel, the driver has a bug that it leaves one uninitialized byte after the command (and this byte is enough to flush the command and render it - thus it fixes the screen corruption), however whe we end up with a non-repeating pixel, there is no byte appended and this results in temporary screen corruption. This patch fixes the screen corruption by always appending a byte 0xAF at the end of URB. It also removes the uninitialized byte. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/udl/udl_fb.c5
-rw-r--r--drivers/gpu/drm/udl/udl_transfer.c11
2 files changed, 11 insertions, 5 deletions
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index 2ebdc6d5a76e..d5583190f3e4 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -137,7 +137,10 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
137 137
138 if (cmd > (char *) urb->transfer_buffer) { 138 if (cmd > (char *) urb->transfer_buffer) {
139 /* Send partial buffer remaining before exiting */ 139 /* Send partial buffer remaining before exiting */
140 int len = cmd - (char *) urb->transfer_buffer; 140 int len;
141 if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
142 *cmd++ = 0xAF;
143 len = cmd - (char *) urb->transfer_buffer;
141 ret = udl_submit_urb(dev, urb, len); 144 ret = udl_submit_urb(dev, urb, len);
142 bytes_sent += len; 145 bytes_sent += len;
143 } else 146 } else
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c
index 0c87b1ac6b68..b992644c17e6 100644
--- a/drivers/gpu/drm/udl/udl_transfer.c
+++ b/drivers/gpu/drm/udl/udl_transfer.c
@@ -153,11 +153,11 @@ static void udl_compress_hline16(
153 raw_pixels_count_byte = cmd++; /* we'll know this later */ 153 raw_pixels_count_byte = cmd++; /* we'll know this later */
154 raw_pixel_start = pixel; 154 raw_pixel_start = pixel;
155 155
156 cmd_pixel_end = pixel + (min(MAX_CMD_PIXELS + 1, 156 cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL,
157 min((int)(pixel_end - pixel) / bpp, 157 (unsigned long)(pixel_end - pixel) / bpp,
158 (int)(cmd_buffer_end - cmd) / 2))) * bpp; 158 (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) * bpp;
159 159
160 prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); 160 prefetch_range((void *) pixel, cmd_pixel_end - pixel);
161 pixel_val16 = get_pixel_val16(pixel, bpp); 161 pixel_val16 = get_pixel_val16(pixel, bpp);
162 162
163 while (pixel < cmd_pixel_end) { 163 while (pixel < cmd_pixel_end) {
@@ -193,6 +193,9 @@ static void udl_compress_hline16(
193 if (pixel > raw_pixel_start) { 193 if (pixel > raw_pixel_start) {
194 /* finalize last RAW span */ 194 /* finalize last RAW span */
195 *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; 195 *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF;
196 } else {
197 /* undo unused byte */
198 cmd--;
196 } 199 }
197 200
198 *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; 201 *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF;