7
7
8
8
#include <linux/bitops.h>
9
9
#include <linux/delay.h>
10
+ #include <linux/gpio/consumer.h>
10
11
#include <linux/init.h>
11
12
#include <linux/kernel.h>
13
+ #include <linux/interrupt.h>
14
+ #include <linux/completion.h>
12
15
#include <linux/module.h>
16
+
13
17
#include <video/mipi_display.h>
14
18
15
19
#include "fbtft.h"
@@ -66,6 +70,62 @@ enum st7789v_command {
66
70
#define MADCTL_MX BIT(6) /* bitmask for column address order */
67
71
#define MADCTL_MY BIT(7) /* bitmask for page address order */
68
72
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
+
69
129
/**
70
130
* init_display() - initialize the display controller
71
131
*
@@ -82,6 +142,12 @@ enum st7789v_command {
82
142
*/
83
143
static int init_display (struct fbtft_par * par )
84
144
{
145
+ int rc ;
146
+
147
+ rc = init_tearing_effect_line (par );
148
+ if (rc )
149
+ return rc ;
150
+
85
151
/* turn off sleep mode */
86
152
write_reg (par , MIPI_DCS_EXIT_SLEEP_MODE );
87
153
mdelay (120 );
@@ -137,6 +203,10 @@ static int init_display(struct fbtft_par *par)
137
203
*/
138
204
write_reg (par , PWCTRL1 , 0xA4 , 0xA1 );
139
205
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
+
140
210
write_reg (par , MIPI_DCS_SET_DISPLAY_ON );
141
211
142
212
if (HSD20_IPS )
@@ -145,6 +215,50 @@ static int init_display(struct fbtft_par *par)
145
215
return 0 ;
146
216
}
147
217
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
+
148
262
/**
149
263
* set_var() - apply LCD properties like rotation and BGR mode
150
264
*
@@ -259,6 +373,7 @@ static struct fbtft_display display = {
259
373
.gamma = HSD20_IPS_GAMMA ,
260
374
.fbtftops = {
261
375
.init_display = init_display ,
376
+ .write_vmem = write_vmem ,
262
377
.set_var = set_var ,
263
378
.set_gamma = set_gamma ,
264
379
.blank = blank ,
0 commit comments