Skip to content

Commit 4e705e1

Browse files
Mikulas Patockabzolnier
authored andcommitted
udlfb: 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 <[email protected]> Cc: [email protected] Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
1 parent 9d0aa60 commit 4e705e1

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

drivers/video/fbdev/udlfb.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/slab.h>
2828
#include <linux/prefetch.h>
2929
#include <linux/delay.h>
30+
#include <asm/unaligned.h>
3031
#include <video/udlfb.h>
3132
#include "edid.h"
3233

@@ -450,17 +451,17 @@ static void dlfb_compress_hline(
450451
raw_pixels_count_byte = cmd++; /* we'll know this later */
451452
raw_pixel_start = pixel;
452453

453-
cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
454-
min((int)(pixel_end - pixel),
455-
(int)(cmd_buffer_end - cmd) / BPP));
454+
cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL,
455+
(unsigned long)(pixel_end - pixel),
456+
(unsigned long)(cmd_buffer_end - 1 - cmd) / BPP);
456457

457-
prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * BPP);
458+
prefetch_range((void *) pixel, (u8 *)cmd_pixel_end - (u8 *)pixel);
458459

459460
while (pixel < cmd_pixel_end) {
460461
const uint16_t * const repeating_pixel = pixel;
461462

462-
*cmd++ = *pixel >> 8;
463-
*cmd++ = *pixel;
463+
put_unaligned_be16(*pixel, cmd);
464+
cmd += 2;
464465
pixel++;
465466

466467
if (unlikely((pixel < cmd_pixel_end) &&
@@ -486,13 +487,16 @@ static void dlfb_compress_hline(
486487
if (pixel > raw_pixel_start) {
487488
/* finalize last RAW span */
488489
*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
490+
} else {
491+
/* undo unused byte */
492+
cmd--;
489493
}
490494

491495
*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
492-
dev_addr += (pixel - cmd_pixel_start) * BPP;
496+
dev_addr += (u8 *)pixel - (u8 *)cmd_pixel_start;
493497
}
494498

495-
if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
499+
if (cmd_buffer_end - MIN_RLX_CMD_BYTES <= cmd) {
496500
/* Fill leftover bytes with no-ops */
497501
if (cmd_buffer_end > cmd)
498502
memset(cmd, 0xAF, cmd_buffer_end - cmd);
@@ -610,8 +614,11 @@ static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
610614
}
611615

612616
if (cmd > (char *) urb->transfer_buffer) {
617+
int len;
618+
if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
619+
*cmd++ = 0xAF;
613620
/* Send partial buffer remaining before exiting */
614-
int len = cmd - (char *) urb->transfer_buffer;
621+
len = cmd - (char *) urb->transfer_buffer;
615622
ret = dlfb_submit_urb(dlfb, urb, len);
616623
bytes_sent += len;
617624
} else
@@ -735,8 +742,11 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
735742
}
736743

737744
if (cmd > (char *) urb->transfer_buffer) {
745+
int len;
746+
if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
747+
*cmd++ = 0xAF;
738748
/* Send partial buffer remaining before exiting */
739-
int len = cmd - (char *) urb->transfer_buffer;
749+
len = cmd - (char *) urb->transfer_buffer;
740750
dlfb_submit_urb(dlfb, urb, len);
741751
bytes_sent += len;
742752
} else

0 commit comments

Comments
 (0)