Skip to content

Commit 1a39243

Browse files
committed
fbtft: fixed software tearing
Signed-off-by: Vincent-FK <vincent.buso@funkey-project.com>
1 parent 1f4ce3b commit 1a39243

6 files changed

Lines changed: 277 additions & 75 deletions

File tree

arch/arm/boot/dts/sun8i-v3s-funkey.dts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@
179179
txbuflen = <115202>;
180180
spi_async_mode = "true";
181181
rotate = <0>;
182-
rotate_soft = <0>;
182+
rotate_soft = <270>;
183183
fps = <100>;
184184
buswidth = <8>;
185185
reset-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; //PB2

drivers/staging/fbtft/fb_st7789v.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,15 @@ static int init_display(struct fbtft_par *par)
156156
//write_reg(par, 0xC6,0x1F); //39Hz
157157
//write_reg(par, 0xC6,0x1A); //44Hz
158158
//write_reg(par, 0xC6,0x17); //48Hz
159+
//write_reg(par, 0xC6,0x16); //49Hz
159160
//write_reg(par, 0xC6,0x15); //50Hz
161+
//write_reg(par, 0xC6,0x14); //52Hz
160162
//write_reg(par, 0xC6,0x12); //55Hz
161163
//write_reg(par, 0xC6,0x10); //58Hz
162-
//write_reg(par, 0xC6,0x0F); //60Hz
163-
write_reg(par, 0xC6,0x09); //60Hz
164+
//write_reg(par, 0xC6,0x0F); //60H
165+
//write_reg(par, 0xC6,0x09); //60Hz
164166
//write_reg(par, 0xC6,0x03); //99Hz
167+
write_reg(par, 0xC6,0x02); //105Hz
165168

166169
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
167170

drivers/staging/fbtft/fbtft-bus.c

Lines changed: 159 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -108,38 +108,157 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...)
108108
}
109109
EXPORT_SYMBOL(fbtft_write_reg8_bus9);
110110

111-
static void spi_complete_cmd_init_data_write(void *arg)
111+
static int prev_write_line_start = -1;
112+
static int prev_write_line_end = -1;
113+
static int write_line_start = -1;
114+
static int write_line_end = -1;
115+
static bool lock = false;
116+
117+
int fbtft_start_new_screen_transfer_async(struct fbtft_par *par)
112118
{
113-
struct fbtft_par *par = (struct fbtft_par *)arg;
114119
// printk("%s\n", __func__);
120+
if (lock)
121+
return -1;
122+
lock = true;
123+
124+
/* Debug fps */
125+
#define FPS_DEBUG 1
126+
#if FPS_DEBUG
127+
long fps;
128+
ktime_t ts_now = ktime_get();
129+
130+
/* First measurement */
131+
if (!ktime_to_ns(par->update_time))
132+
par->update_time = ts_now;
133+
134+
fps = ktime_us_delta(ts_now, par->update_time);
135+
par->update_time = ts_now;
136+
fps = fps ? 1000000 / fps : 0;
137+
138+
if (fps) {
139+
par->avg_fps += fps;
140+
par->nb_fps_values++;
141+
142+
if (par->nb_fps_values == 200) {
143+
fbtft_par_dbg(DEBUG_TIME_EACH_UPDATE, par,
144+
"Display update: fps=%ld\n", par->avg_fps / par->nb_fps_values);
145+
par->avg_fps = 0;
146+
par->nb_fps_values = 0;
147+
}
148+
}
115149

116-
/* Start new data write (full display) */
117-
int len = par->info->var.yres * par->info->fix.line_length;
118-
fbtft_write_vmem16_bus8_async(par, 0, len);
150+
#endif //FPS_DEBUG
151+
152+
/* Post process screen for doufle buf cpy, notifs, rotation soft... */
153+
fbtft_post_process_screen(par);
154+
155+
/* new line to write */
156+
write_line_start = par->write_line_start;
157+
write_line_end = par->write_line_end;
158+
par->write_line_start = -1;
159+
par->write_line_end = -1;
160+
161+
/* Set window for interlacing */
162+
if (par->interlacing) {
163+
par->length_data_transfer = par->info->var.yres * 2;
164+
write_line_start = par->odd_line?1:0;
165+
write_line_end = write_line_start;
166+
fbtft_write_cmd_window_line(par);
167+
168+
} else {
169+
/* Start sending full screen */
170+
par->length_data_transfer = par->info->var.yres * par->info->fix.line_length;
171+
write_line_start = 0;
172+
write_line_end = par->info->var.yres - 1;
173+
fbtft_write_init_cmd_data_transfers(par);
174+
}
175+
return 0;
119176
}
177+
EXPORT_SYMBOL(fbtft_start_new_screen_transfer_async);
120178

121-
static void spi_complete_data_write(void *arg)
179+
static u8 cmd_window_line = MIPI_DCS_SET_PAGE_ADDRESS;
180+
static u8 buf_ylim[4];
181+
182+
static void spi_complete_cmd_window_line(void *arg)
122183
{
123184
struct fbtft_par *par = (struct fbtft_par *)arg;
124185
// printk("%s\n", __func__);
125186

126-
/* sleep */
127-
// msleep(1);
187+
/* Start data write for line info */
188+
fbtft_write_data_window_line(par);
189+
}
190+
191+
int fbtft_write_cmd_window_line(struct fbtft_par *par){
192+
193+
int ret = 0;
194+
195+
//printk("%s\n", __func__);
196+
197+
/* Resetting to 0 for incoming cmd init data write */
198+
if (gpio_is_valid(par->gpio.dc))
199+
gpio_set_value(par->gpio.dc, 0);
128200

129201
/* Start sending cmd init data */
202+
ret = par->fbtftops.write_async(par, &cmd_window_line, 1, spi_complete_cmd_window_line);
203+
if (ret < 0)
204+
dev_err(par->info->device,
205+
"write() failed and returned %d\n", ret);
206+
207+
return ret;
208+
209+
}
210+
EXPORT_SYMBOL(fbtft_write_cmd_window_line);
211+
212+
static void spi_complete_data_window_line(void *arg)
213+
{
214+
struct fbtft_par *par = (struct fbtft_par *) arg;
215+
//printk("%s\n", __func__);
216+
217+
/* Start sending cmd for real data transfer */
130218
fbtft_write_init_cmd_data_transfers(par);
131219
}
132220

221+
int fbtft_write_data_window_line(struct fbtft_par *par)
222+
{
223+
int ret = 0;
224+
225+
/* Setting new line coordinates */
226+
buf_ylim[0] = (write_line_start >> 8) & 0xFF;
227+
buf_ylim[1] = write_line_start & 0xFF;
228+
buf_ylim[2] = (write_line_end >> 8) & 0xFF;
229+
buf_ylim[3] = write_line_end & 0xFF;
230+
231+
//printk("%s, buf[0] = %d, buf[1] = %d, buf[2] = %d, buf[3] = %d\n", __func__, buf[0], buf[1], buf[2], buf[3]);
232+
233+
/* Resetting to 1 for incoming data */
234+
if (gpio_is_valid(par->gpio.dc))
235+
gpio_set_value(par->gpio.dc, 1);
236+
237+
/* Start sending window_line data */
238+
ret = par->fbtftops.write_async(par, buf_ylim, 4, spi_complete_data_window_line);
239+
if (ret < 0)
240+
dev_err(par->info->device,
241+
"write() failed and returned %d\n", ret);
242+
243+
return ret;
244+
}
245+
EXPORT_SYMBOL(fbtft_write_data_window_line);
246+
247+
static void spi_complete_cmd_init_data_write(void *arg)
248+
{
249+
struct fbtft_par *par = (struct fbtft_par *) arg;
250+
//printk("%s\n", __func__);
251+
252+
fbtft_write_vmem16_bus8_async(par, write_line_start * par->info->fix.line_length, par->length_data_transfer);
253+
}
254+
133255
int fbtft_write_init_cmd_data_transfers(struct fbtft_par *par)
134256
{
135257
static u8 init_data_cmd_buf = MIPI_DCS_WRITE_MEMORY_START;
136258
int ret = 0;
137259

138260
// printk("%s\n", __func__);
139261

140-
/* Post process */
141-
fbtft_post_process_screen(par, 0, par->info->var.yres - 1);
142-
143262
/* Resetting to 0 for incoming cmd init data write */
144263
if (gpio_is_valid(par->gpio.dc))
145264
gpio_set_value(par->gpio.dc, 0);
@@ -150,36 +269,40 @@ int fbtft_write_init_cmd_data_transfers(struct fbtft_par *par)
150269
if (ret < 0)
151270
dev_err(par->info->device, "write() failed and returned %d\n", ret);
152271

153-
/* Debug fps */
154-
#define FPS_DEBUG 0
155-
#if FPS_DEBUG
156-
ktime_t ts_now = ktime_get();
157-
158-
/* First measurement */
159-
if (!ktime_to_ns(par->update_time))
160-
par->update_time = ts_now;
161-
162-
long fps = ktime_us_delta(ts_now, par->update_time);
163-
par->update_time = ts_now;
164-
fps = fps ? 1000000 / fps : 0;
272+
return ret;
273+
}
274+
EXPORT_SYMBOL(fbtft_write_init_cmd_data_transfers);
165275

166-
if (fps) {
167-
par->avg_fps += fps;
168-
par->nb_fps_values++;
276+
static void spi_complete_data_write(void *arg)
277+
{
278+
struct fbtft_par *par = (struct fbtft_par *) arg;
279+
//printk("%s, par->interlacing=%d, write_line_start=%d\n", __func__, par->interlacing?1:0, write_line_start);
169280

170-
if (par->nb_fps_values == 200) {
171-
dev_info(par->info->device, "Display update: fps=%ld\n",
172-
par->avg_fps / par->nb_fps_values);
173-
par->avg_fps = 0;
174-
par->nb_fps_values = 0;
281+
/* sleep */
282+
//msleep(1);
283+
284+
if (par->interlacing) {
285+
/* Check if last line */
286+
bool last_line = (par->odd_line && write_line_start >= par->info->var.yres-1) ||
287+
(!par->odd_line && write_line_start >= par->info->var.yres-2);
288+
289+
if (last_line) {
290+
/* Start sending cmd init data */
291+
par->odd_line = !par->odd_line;
292+
lock = false;
293+
fbtft_start_new_screen_transfer_async(par);
294+
} else {
295+
write_line_start += 2;
296+
write_line_end = write_line_start;
297+
298+
/* Setting window for next line */
299+
fbtft_write_cmd_window_line(par);
175300
}
301+
} else {
302+
lock = false;
303+
fbtft_start_new_screen_transfer_async(par);
176304
}
177-
178-
#endif // FPS_DEBUG
179-
180-
return ret;
181305
}
182-
EXPORT_SYMBOL(fbtft_write_init_cmd_data_transfers);
183306

184307
/*****************************************************************************
185308
*
@@ -203,8 +326,6 @@ int fbtft_write_vmem16_bus8_async(struct fbtft_par *par, size_t offset, size_t l
203326
__func__, offset, len);
204327

205328
remain = len / 2;
206-
//vmem16 = (u16 *)(par->info->screen_buffer + offset);
207-
//vmem16 = (u16 *)(par->vmem_post_process + offset);
208329
vmem16 = (u16 *)(par->vmem_ptr + offset);
209330

210331
if (par->gpio.dc != -1)

0 commit comments

Comments
 (0)