Skip to content

Commit fa7d3e6

Browse files
Carlisgregkh
authored andcommitted
staging: fbtft: add tearing signal detect
For st7789v IC, when we need continuous full screen refresh, it is best to wait for the tearing effect line signal to arrive to avoid screen tearing. Signed-off-by: Carlis <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 95897fd commit fa7d3e6

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

drivers/staging/fbtft/fb_st7789v.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77

88
#include <linux/bitops.h>
99
#include <linux/delay.h>
10+
#include <linux/gpio/consumer.h>
1011
#include <linux/init.h>
1112
#include <linux/kernel.h>
13+
#include <linux/interrupt.h>
14+
#include <linux/completion.h>
1215
#include <linux/module.h>
16+
1317
#include <video/mipi_display.h>
1418

1519
#include "fbtft.h"
@@ -66,6 +70,62 @@ enum st7789v_command {
6670
#define MADCTL_MX BIT(6) /* bitmask for column address order */
6771
#define MADCTL_MY BIT(7) /* bitmask for page address order */
6872

73+
/* 60Hz for 16.6ms, configured as 2*16.6ms */
74+
#define PANEL_TE_TIMEOUT_MS 33
75+
76+
static struct completion panel_te; /* completion for panel TE line */
77+
static int irq_te; /* Linux IRQ for LCD TE line */
78+
79+
static irqreturn_t panel_te_handler(int irq, void *data)
80+
{
81+
complete(&panel_te);
82+
return IRQ_HANDLED;
83+
}
84+
85+
/*
86+
* init_tearing_effect_line() - init tearing effect line.
87+
* @par: FBTFT parameter object.
88+
*
89+
* Return: 0 on success, or a negative error code otherwise.
90+
*/
91+
static int init_tearing_effect_line(struct fbtft_par *par)
92+
{
93+
struct device *dev = par->info->device;
94+
struct gpio_desc *te;
95+
int rc, irq;
96+
97+
te = gpiod_get_optional(dev, "te", GPIOD_IN);
98+
if (IS_ERR(te))
99+
return dev_err_probe(dev, PTR_ERR(te), "Failed to request te GPIO\n");
100+
101+
/* if te is NULL, indicating no configuration, directly return success */
102+
if (!te) {
103+
irq_te = 0;
104+
return 0;
105+
}
106+
107+
irq = gpiod_to_irq(te);
108+
109+
/* GPIO is locked as an IRQ, we may drop the reference */
110+
gpiod_put(te);
111+
112+
if (irq < 0)
113+
return irq;
114+
115+
irq_te = irq;
116+
init_completion(&panel_te);
117+
118+
/* The effective state is high and lasts no more than 1000 microseconds */
119+
rc = devm_request_irq(dev, irq_te, panel_te_handler,
120+
IRQF_TRIGGER_RISING, "TE_GPIO", par);
121+
if (rc)
122+
return dev_err_probe(dev, rc, "TE IRQ request failed.\n");
123+
124+
disable_irq_nosync(irq_te);
125+
126+
return 0;
127+
}
128+
69129
/**
70130
* init_display() - initialize the display controller
71131
*
@@ -82,6 +142,12 @@ enum st7789v_command {
82142
*/
83143
static int init_display(struct fbtft_par *par)
84144
{
145+
int rc;
146+
147+
rc = init_tearing_effect_line(par);
148+
if (rc)
149+
return rc;
150+
85151
/* turn off sleep mode */
86152
write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
87153
mdelay(120);
@@ -137,6 +203,10 @@ static int init_display(struct fbtft_par *par)
137203
*/
138204
write_reg(par, PWCTRL1, 0xA4, 0xA1);
139205

206+
/* TE line output is off by default when powering on */
207+
if (irq_te)
208+
write_reg(par, MIPI_DCS_SET_TEAR_ON, 0x00);
209+
140210
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
141211

142212
if (HSD20_IPS)
@@ -145,6 +215,50 @@ static int init_display(struct fbtft_par *par)
145215
return 0;
146216
}
147217

218+
/*
219+
* write_vmem() - write data to display.
220+
* @par: FBTFT parameter object.
221+
* @offset: offset from screen_buffer.
222+
* @len: the length of data to be writte.
223+
*
224+
* Return: 0 on success, or a negative error code otherwise.
225+
*/
226+
static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
227+
{
228+
struct device *dev = par->info->device;
229+
int ret;
230+
231+
if (irq_te) {
232+
enable_irq(irq_te);
233+
reinit_completion(&panel_te);
234+
ret = wait_for_completion_timeout(&panel_te,
235+
msecs_to_jiffies(PANEL_TE_TIMEOUT_MS));
236+
if (ret == 0)
237+
dev_err(dev, "wait panel TE timeout\n");
238+
239+
disable_irq(irq_te);
240+
}
241+
242+
switch (par->pdata->display.buswidth) {
243+
case 8:
244+
ret = fbtft_write_vmem16_bus8(par, offset, len);
245+
break;
246+
case 9:
247+
ret = fbtft_write_vmem16_bus9(par, offset, len);
248+
break;
249+
case 16:
250+
ret = fbtft_write_vmem16_bus16(par, offset, len);
251+
break;
252+
default:
253+
dev_err(dev, "Unsupported buswidth %d\n",
254+
par->pdata->display.buswidth);
255+
ret = 0;
256+
break;
257+
}
258+
259+
return ret;
260+
}
261+
148262
/**
149263
* set_var() - apply LCD properties like rotation and BGR mode
150264
*
@@ -259,6 +373,7 @@ static struct fbtft_display display = {
259373
.gamma = HSD20_IPS_GAMMA,
260374
.fbtftops = {
261375
.init_display = init_display,
376+
.write_vmem = write_vmem,
262377
.set_var = set_var,
263378
.set_gamma = set_gamma,
264379
.blank = blank,

0 commit comments

Comments
 (0)