@@ -108,38 +108,157 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...)
108108}
109109EXPORT_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+
133255int 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