]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/media/platform/sti/bdisp/bdisp-hw.c
Merge tag 'media/v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[linux.git] / drivers / media / platform / sti / bdisp / bdisp-hw.c
1 /*
2  * Copyright (C) STMicroelectronics SA 2014
3  * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
4  * License terms:  GNU General Public License (GPL), version 2
5  */
6
7 #include <linux/delay.h>
8
9 #include "bdisp.h"
10 #include "bdisp-filter.h"
11 #include "bdisp-reg.h"
12
13 /* Max width of the source frame in a single node */
14 #define MAX_SRC_WIDTH           2048
15
16 /* Reset & boot poll config */
17 #define POLL_RST_MAX            50
18 #define POLL_RST_DELAY_MS       20
19
20 enum bdisp_target_plan {
21         BDISP_RGB,
22         BDISP_Y,
23         BDISP_CBCR
24 };
25
26 struct bdisp_op_cfg {
27         bool cconv;          /* RGB - YUV conversion */
28         bool hflip;          /* Horizontal flip */
29         bool vflip;          /* Vertical flip */
30         bool wide;           /* Wide (>MAX_SRC_WIDTH) */
31         bool scale;          /* Scale */
32         u16  h_inc;          /* Horizontal increment in 6.10 format */
33         u16  v_inc;          /* Vertical increment in 6.10 format */
34         bool src_interlaced; /* is the src an interlaced buffer */
35         u8   src_nbp;        /* nb of planes of the src */
36         bool src_yuv;        /* is the src a YUV color format */
37         bool src_420;        /* is the src 4:2:0 chroma subsampled */
38         u8   dst_nbp;        /* nb of planes of the dst */
39         bool dst_yuv;        /* is the dst a YUV color format */
40         bool dst_420;        /* is the dst 4:2:0 chroma subsampled */
41 };
42
43 struct bdisp_filter_addr {
44         u16 min;             /* Filter min scale factor (6.10 fixed point) */
45         u16 max;             /* Filter max scale factor (6.10 fixed point) */
46         void *virt;          /* Virtual address for filter table */
47         dma_addr_t paddr;    /* Physical address for filter table */
48 };
49
50 static const struct bdisp_filter_h_spec bdisp_h_spec[] = {
51         {
52                 .min = 0,
53                 .max = 921,
54                 .coef = {
55                         0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
56                         0x00, 0x00, 0xff, 0x07, 0x3d, 0xfc, 0x01, 0x00,
57                         0x00, 0x01, 0xfd, 0x11, 0x36, 0xf9, 0x02, 0x00,
58                         0x00, 0x01, 0xfb, 0x1b, 0x2e, 0xf9, 0x02, 0x00,
59                         0x00, 0x01, 0xf9, 0x26, 0x26, 0xf9, 0x01, 0x00,
60                         0x00, 0x02, 0xf9, 0x30, 0x19, 0xfb, 0x01, 0x00,
61                         0x00, 0x02, 0xf9, 0x39, 0x0e, 0xfd, 0x01, 0x00,
62                         0x00, 0x01, 0xfc, 0x3e, 0x06, 0xff, 0x00, 0x00
63                 }
64         },
65         {
66                 .min = 921,
67                 .max = 1024,
68                 .coef = {
69                         0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
70                         0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe,
71                         0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc,
72                         0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb,
73                         0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb,
74                         0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb,
75                         0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd,
76                         0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff
77                 }
78         },
79         {
80                 .min = 1024,
81                 .max = 1126,
82                 .coef = {
83                         0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
84                         0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe,
85                         0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc,
86                         0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb,
87                         0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb,
88                         0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb,
89                         0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd,
90                         0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff
91                 }
92         },
93         {
94                 .min = 1126,
95                 .max = 1228,
96                 .coef = {
97                         0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
98                         0xff, 0x03, 0xfd, 0x08, 0x3e, 0xf9, 0x04, 0xfe,
99                         0xfd, 0x06, 0xf8, 0x13, 0x3b, 0xf4, 0x07, 0xfc,
100                         0xfb, 0x08, 0xf5, 0x1f, 0x34, 0xf1, 0x09, 0xfb,
101                         0xfb, 0x09, 0xf2, 0x2b, 0x2a, 0xf1, 0x09, 0xfb,
102                         0xfb, 0x09, 0xf2, 0x35, 0x1e, 0xf4, 0x08, 0xfb,
103                         0xfc, 0x07, 0xf5, 0x3c, 0x12, 0xf7, 0x06, 0xfd,
104                         0xfe, 0x04, 0xfa, 0x3f, 0x07, 0xfc, 0x03, 0xff
105                 }
106         },
107         {
108                 .min = 1228,
109                 .max = 1331,
110                 .coef = {
111                         0xfd, 0x04, 0xfc, 0x05, 0x39, 0x05, 0xfc, 0x04,
112                         0xfc, 0x06, 0xf9, 0x0c, 0x39, 0xfe, 0x00, 0x02,
113                         0xfb, 0x08, 0xf6, 0x17, 0x35, 0xf9, 0x02, 0x00,
114                         0xfc, 0x08, 0xf4, 0x20, 0x30, 0xf4, 0x05, 0xff,
115                         0xfd, 0x07, 0xf4, 0x29, 0x28, 0xf3, 0x07, 0xfd,
116                         0xff, 0x05, 0xf5, 0x31, 0x1f, 0xf3, 0x08, 0xfc,
117                         0x00, 0x02, 0xf9, 0x38, 0x14, 0xf6, 0x08, 0xfb,
118                         0x02, 0x00, 0xff, 0x3a, 0x0b, 0xf8, 0x06, 0xfc
119                 }
120         },
121         {
122                 .min = 1331,
123                 .max = 1433,
124                 .coef = {
125                         0xfc, 0x06, 0xf9, 0x09, 0x34, 0x09, 0xf9, 0x06,
126                         0xfd, 0x07, 0xf7, 0x10, 0x32, 0x02, 0xfc, 0x05,
127                         0xfe, 0x07, 0xf6, 0x17, 0x2f, 0xfc, 0xff, 0x04,
128                         0xff, 0x06, 0xf5, 0x20, 0x2a, 0xf9, 0x01, 0x02,
129                         0x00, 0x04, 0xf6, 0x27, 0x25, 0xf6, 0x04, 0x00,
130                         0x02, 0x01, 0xf9, 0x2d, 0x1d, 0xf5, 0x06, 0xff,
131                         0x04, 0xff, 0xfd, 0x31, 0x15, 0xf5, 0x07, 0xfe,
132                         0x05, 0xfc, 0x02, 0x35, 0x0d, 0xf7, 0x07, 0xfd
133                 }
134         },
135         {
136                 .min = 1433,
137                 .max = 1536,
138                 .coef = {
139                         0xfe, 0x06, 0xf8, 0x0b, 0x30, 0x0b, 0xf8, 0x06,
140                         0xff, 0x06, 0xf7, 0x12, 0x2d, 0x05, 0xfa, 0x06,
141                         0x00, 0x04, 0xf6, 0x18, 0x2c, 0x00, 0xfc, 0x06,
142                         0x01, 0x02, 0xf7, 0x1f, 0x27, 0xfd, 0xff, 0x04,
143                         0x03, 0x00, 0xf9, 0x24, 0x24, 0xf9, 0x00, 0x03,
144                         0x04, 0xff, 0xfd, 0x29, 0x1d, 0xf7, 0x02, 0x01,
145                         0x06, 0xfc, 0x00, 0x2d, 0x17, 0xf6, 0x04, 0x00,
146                         0x06, 0xfa, 0x05, 0x30, 0x0f, 0xf7, 0x06, 0xff
147                 }
148         },
149         {
150                 .min = 1536,
151                 .max = 2048,
152                 .coef = {
153                         0x05, 0xfd, 0xfb, 0x13, 0x25, 0x13, 0xfb, 0xfd,
154                         0x05, 0xfc, 0xfd, 0x17, 0x24, 0x0f, 0xf9, 0xff,
155                         0x04, 0xfa, 0xff, 0x1b, 0x24, 0x0b, 0xf9, 0x00,
156                         0x03, 0xf9, 0x01, 0x1f, 0x23, 0x08, 0xf8, 0x01,
157                         0x02, 0xf9, 0x04, 0x22, 0x20, 0x04, 0xf9, 0x02,
158                         0x01, 0xf8, 0x08, 0x25, 0x1d, 0x01, 0xf9, 0x03,
159                         0x00, 0xf9, 0x0c, 0x25, 0x1a, 0xfe, 0xfa, 0x04,
160                         0xff, 0xf9, 0x10, 0x26, 0x15, 0xfc, 0xfc, 0x05
161                 }
162         },
163         {
164                 .min = 2048,
165                 .max = 3072,
166                 .coef = {
167                         0xfc, 0xfd, 0x06, 0x13, 0x18, 0x13, 0x06, 0xfd,
168                         0xfc, 0xfe, 0x08, 0x15, 0x17, 0x12, 0x04, 0xfc,
169                         0xfb, 0xfe, 0x0a, 0x16, 0x18, 0x10, 0x03, 0xfc,
170                         0xfb, 0x00, 0x0b, 0x18, 0x17, 0x0f, 0x01, 0xfb,
171                         0xfb, 0x00, 0x0d, 0x19, 0x17, 0x0d, 0x00, 0xfb,
172                         0xfb, 0x01, 0x0f, 0x19, 0x16, 0x0b, 0x00, 0xfb,
173                         0xfc, 0x03, 0x11, 0x19, 0x15, 0x09, 0xfe, 0xfb,
174                         0xfc, 0x04, 0x12, 0x1a, 0x12, 0x08, 0xfe, 0xfc
175                 }
176         },
177         {
178                 .min = 3072,
179                 .max = 4096,
180                 .coef = {
181                         0xfe, 0x02, 0x09, 0x0f, 0x0e, 0x0f, 0x09, 0x02,
182                         0xff, 0x02, 0x09, 0x0f, 0x10, 0x0e, 0x08, 0x01,
183                         0xff, 0x03, 0x0a, 0x10, 0x10, 0x0d, 0x07, 0x00,
184                         0x00, 0x04, 0x0b, 0x10, 0x0f, 0x0c, 0x06, 0x00,
185                         0x00, 0x05, 0x0c, 0x10, 0x0e, 0x0c, 0x05, 0x00,
186                         0x00, 0x06, 0x0c, 0x11, 0x0e, 0x0b, 0x04, 0x00,
187                         0x00, 0x07, 0x0d, 0x11, 0x0f, 0x0a, 0x03, 0xff,
188                         0x01, 0x08, 0x0e, 0x11, 0x0e, 0x09, 0x02, 0xff
189                 }
190         },
191         {
192                 .min = 4096,
193                 .max = 5120,
194                 .coef = {
195                         0x00, 0x04, 0x09, 0x0c, 0x0e, 0x0c, 0x09, 0x04,
196                         0x01, 0x05, 0x09, 0x0c, 0x0d, 0x0c, 0x08, 0x04,
197                         0x01, 0x05, 0x0a, 0x0c, 0x0e, 0x0b, 0x08, 0x03,
198                         0x02, 0x06, 0x0a, 0x0d, 0x0c, 0x0b, 0x07, 0x03,
199                         0x02, 0x07, 0x0a, 0x0d, 0x0d, 0x0a, 0x07, 0x02,
200                         0x03, 0x07, 0x0b, 0x0d, 0x0c, 0x0a, 0x06, 0x02,
201                         0x03, 0x08, 0x0b, 0x0d, 0x0d, 0x0a, 0x05, 0x01,
202                         0x04, 0x08, 0x0c, 0x0d, 0x0c, 0x09, 0x05, 0x01
203                 }
204         },
205         {
206                 .min = 5120,
207                 .max = 65535,
208                 .coef = {
209                         0x03, 0x06, 0x09, 0x0b, 0x09, 0x0b, 0x09, 0x06,
210                         0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05,
211                         0x03, 0x06, 0x09, 0x0b, 0x0c, 0x0a, 0x08, 0x05,
212                         0x04, 0x07, 0x09, 0x0b, 0x0b, 0x0a, 0x08, 0x04,
213                         0x04, 0x07, 0x0a, 0x0b, 0x0b, 0x0a, 0x07, 0x04,
214                         0x04, 0x08, 0x0a, 0x0b, 0x0b, 0x09, 0x07, 0x04,
215                         0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03,
216                         0x05, 0x08, 0x0a, 0x0b, 0x0c, 0x09, 0x06, 0x03
217                 }
218         }
219 };
220
221 #define NB_H_FILTER ARRAY_SIZE(bdisp_h_spec)
222
223
224 static const struct bdisp_filter_v_spec bdisp_v_spec[] = {
225         {
226                 .min = 0,
227                 .max = 1024,
228                 .coef = {
229                         0x00, 0x00, 0x40, 0x00, 0x00,
230                         0x00, 0x06, 0x3d, 0xfd, 0x00,
231                         0xfe, 0x0f, 0x38, 0xfb, 0x00,
232                         0xfd, 0x19, 0x2f, 0xfb, 0x00,
233                         0xfc, 0x24, 0x24, 0xfc, 0x00,
234                         0xfb, 0x2f, 0x19, 0xfd, 0x00,
235                         0xfb, 0x38, 0x0f, 0xfe, 0x00,
236                         0xfd, 0x3d, 0x06, 0x00, 0x00
237                 }
238         },
239         {
240                 .min = 1024,
241                 .max = 1331,
242                 .coef = {
243                         0xfc, 0x05, 0x3e, 0x05, 0xfc,
244                         0xf8, 0x0e, 0x3b, 0xff, 0x00,
245                         0xf5, 0x18, 0x38, 0xf9, 0x02,
246                         0xf4, 0x21, 0x31, 0xf5, 0x05,
247                         0xf4, 0x2a, 0x27, 0xf4, 0x07,
248                         0xf6, 0x30, 0x1e, 0xf4, 0x08,
249                         0xf9, 0x35, 0x15, 0xf6, 0x07,
250                         0xff, 0x37, 0x0b, 0xf9, 0x06
251                 }
252         },
253         {
254                 .min = 1331,
255                 .max = 1433,
256                 .coef = {
257                         0xf8, 0x0a, 0x3c, 0x0a, 0xf8,
258                         0xf6, 0x12, 0x3b, 0x02, 0xfb,
259                         0xf4, 0x1b, 0x35, 0xfd, 0xff,
260                         0xf4, 0x23, 0x30, 0xf8, 0x01,
261                         0xf6, 0x29, 0x27, 0xf6, 0x04,
262                         0xf9, 0x2e, 0x1e, 0xf5, 0x06,
263                         0xfd, 0x31, 0x16, 0xf6, 0x06,
264                         0x02, 0x32, 0x0d, 0xf8, 0x07
265                 }
266         },
267         {
268                 .min = 1433,
269                 .max = 1536,
270                 .coef = {
271                         0xf6, 0x0e, 0x38, 0x0e, 0xf6,
272                         0xf5, 0x15, 0x38, 0x06, 0xf8,
273                         0xf5, 0x1d, 0x33, 0x00, 0xfb,
274                         0xf6, 0x23, 0x2d, 0xfc, 0xfe,
275                         0xf9, 0x28, 0x26, 0xf9, 0x00,
276                         0xfc, 0x2c, 0x1e, 0xf7, 0x03,
277                         0x00, 0x2e, 0x18, 0xf6, 0x04,
278                         0x05, 0x2e, 0x11, 0xf7, 0x05
279                 }
280         },
281         {
282                 .min = 1536,
283                 .max = 2048,
284                 .coef = {
285                         0xfb, 0x13, 0x24, 0x13, 0xfb,
286                         0xfd, 0x17, 0x23, 0x0f, 0xfa,
287                         0xff, 0x1a, 0x23, 0x0b, 0xf9,
288                         0x01, 0x1d, 0x22, 0x07, 0xf9,
289                         0x04, 0x20, 0x1f, 0x04, 0xf9,
290                         0x07, 0x22, 0x1c, 0x01, 0xfa,
291                         0x0b, 0x24, 0x17, 0xff, 0xfb,
292                         0x0f, 0x24, 0x14, 0xfd, 0xfc
293                 }
294         },
295         {
296                 .min = 2048,
297                 .max = 3072,
298                 .coef = {
299                         0x05, 0x10, 0x16, 0x10, 0x05,
300                         0x06, 0x11, 0x16, 0x0f, 0x04,
301                         0x08, 0x13, 0x15, 0x0e, 0x02,
302                         0x09, 0x14, 0x16, 0x0c, 0x01,
303                         0x0b, 0x15, 0x15, 0x0b, 0x00,
304                         0x0d, 0x16, 0x13, 0x0a, 0x00,
305                         0x0f, 0x17, 0x13, 0x08, 0xff,
306                         0x11, 0x18, 0x12, 0x07, 0xfe
307                 }
308         },
309         {
310                 .min = 3072,
311                 .max = 4096,
312                 .coef = {
313                         0x09, 0x0f, 0x10, 0x0f, 0x09,
314                         0x09, 0x0f, 0x12, 0x0e, 0x08,
315                         0x0a, 0x10, 0x11, 0x0e, 0x07,
316                         0x0b, 0x11, 0x11, 0x0d, 0x06,
317                         0x0c, 0x11, 0x12, 0x0c, 0x05,
318                         0x0d, 0x12, 0x11, 0x0c, 0x04,
319                         0x0e, 0x12, 0x11, 0x0b, 0x04,
320                         0x0f, 0x13, 0x11, 0x0a, 0x03
321                 }
322         },
323         {
324                 .min = 4096,
325                 .max = 5120,
326                 .coef = {
327                         0x0a, 0x0e, 0x10, 0x0e, 0x0a,
328                         0x0b, 0x0e, 0x0f, 0x0e, 0x0a,
329                         0x0b, 0x0f, 0x10, 0x0d, 0x09,
330                         0x0c, 0x0f, 0x10, 0x0d, 0x08,
331                         0x0d, 0x0f, 0x0f, 0x0d, 0x08,
332                         0x0d, 0x10, 0x10, 0x0c, 0x07,
333                         0x0e, 0x10, 0x0f, 0x0c, 0x07,
334                         0x0f, 0x10, 0x10, 0x0b, 0x06
335                 }
336         },
337         {
338                 .min = 5120,
339                 .max = 65535,
340                 .coef = {
341                         0x0b, 0x0e, 0x0e, 0x0e, 0x0b,
342                         0x0b, 0x0e, 0x0f, 0x0d, 0x0b,
343                         0x0c, 0x0e, 0x0f, 0x0d, 0x0a,
344                         0x0c, 0x0e, 0x0f, 0x0d, 0x0a,
345                         0x0d, 0x0f, 0x0e, 0x0d, 0x09,
346                         0x0d, 0x0f, 0x0f, 0x0c, 0x09,
347                         0x0e, 0x0f, 0x0e, 0x0c, 0x09,
348                         0x0e, 0x0f, 0x0f, 0x0c, 0x08
349                 }
350         }
351 };
352
353 #define NB_V_FILTER ARRAY_SIZE(bdisp_v_spec)
354
355 static struct bdisp_filter_addr bdisp_h_filter[NB_H_FILTER];
356 static struct bdisp_filter_addr bdisp_v_filter[NB_V_FILTER];
357
358 /**
359  * bdisp_hw_reset
360  * @bdisp:      bdisp entity
361  *
362  * Resets HW
363  *
364  * RETURNS:
365  * 0 on success.
366  */
367 int bdisp_hw_reset(struct bdisp_dev *bdisp)
368 {
369         unsigned int i;
370
371         dev_dbg(bdisp->dev, "%s\n", __func__);
372
373         /* Mask Interrupt */
374         writel(0, bdisp->regs + BLT_ITM0);
375
376         /* Reset */
377         writel(readl(bdisp->regs + BLT_CTL) | BLT_CTL_RESET,
378                bdisp->regs + BLT_CTL);
379         writel(0, bdisp->regs + BLT_CTL);
380
381         /* Wait for reset done */
382         for (i = 0; i < POLL_RST_MAX; i++) {
383                 if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE)
384                         break;
385                 msleep(POLL_RST_DELAY_MS);
386         }
387         if (i == POLL_RST_MAX)
388                 dev_err(bdisp->dev, "Reset timeout\n");
389
390         return (i == POLL_RST_MAX) ? -EAGAIN : 0;
391 }
392
393 /**
394  * bdisp_hw_get_and_clear_irq
395  * @bdisp:      bdisp entity
396  *
397  * Read then reset interrupt status
398  *
399  * RETURNS:
400  * 0 if expected interrupt was raised.
401  */
402 int bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp)
403 {
404         u32 its;
405
406         its = readl(bdisp->regs + BLT_ITS);
407
408         /* Check for the only expected IT: LastNode of AQ1 */
409         if (!(its & BLT_ITS_AQ1_LNA)) {
410                 dev_dbg(bdisp->dev, "Unexpected IT status: 0x%08X\n", its);
411                 writel(its, bdisp->regs + BLT_ITS);
412                 return -1;
413         }
414
415         /* Clear and mask */
416         writel(its, bdisp->regs + BLT_ITS);
417         writel(0, bdisp->regs + BLT_ITM0);
418
419         return 0;
420 }
421
422 /**
423  * bdisp_hw_free_nodes
424  * @ctx:        bdisp context
425  *
426  * Free node memory
427  *
428  * RETURNS:
429  * None
430  */
431 void bdisp_hw_free_nodes(struct bdisp_ctx *ctx)
432 {
433         if (ctx && ctx->node[0]) {
434                 DEFINE_DMA_ATTRS(attrs);
435
436                 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
437                 dma_free_attrs(ctx->bdisp_dev->dev,
438                                sizeof(struct bdisp_node) * MAX_NB_NODE,
439                                ctx->node[0], ctx->node_paddr[0], &attrs);
440         }
441 }
442
443 /**
444  * bdisp_hw_alloc_nodes
445  * @ctx:        bdisp context
446  *
447  * Allocate dma memory for nodes
448  *
449  * RETURNS:
450  * 0 on success
451  */
452 int bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx)
453 {
454         struct device *dev = ctx->bdisp_dev->dev;
455         unsigned int i, node_size = sizeof(struct bdisp_node);
456         void *base;
457         dma_addr_t paddr;
458         DEFINE_DMA_ATTRS(attrs);
459
460         /* Allocate all the nodes within a single memory page */
461         dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
462         base = dma_alloc_attrs(dev, node_size * MAX_NB_NODE, &paddr,
463                                GFP_KERNEL | GFP_DMA, &attrs);
464         if (!base) {
465                 dev_err(dev, "%s no mem\n", __func__);
466                 return -ENOMEM;
467         }
468
469         memset(base, 0, node_size * MAX_NB_NODE);
470
471         for (i = 0; i < MAX_NB_NODE; i++) {
472                 ctx->node[i] = base;
473                 ctx->node_paddr[i] = paddr;
474                 dev_dbg(dev, "node[%d]=0x%p (paddr=%pad)\n", i, ctx->node[i],
475                         &paddr);
476                 base += node_size;
477                 paddr += node_size;
478         }
479
480         return 0;
481 }
482
483 /**
484  * bdisp_hw_free_filters
485  * @dev:        device
486  *
487  * Free filters memory
488  *
489  * RETURNS:
490  * None
491  */
492 void bdisp_hw_free_filters(struct device *dev)
493 {
494         int size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER);
495
496         if (bdisp_h_filter[0].virt) {
497                 DEFINE_DMA_ATTRS(attrs);
498
499                 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
500                 dma_free_attrs(dev, size, bdisp_h_filter[0].virt,
501                                bdisp_h_filter[0].paddr, &attrs);
502         }
503 }
504
505 /**
506  * bdisp_hw_alloc_filters
507  * @dev:        device
508  *
509  * Allocate dma memory for filters
510  *
511  * RETURNS:
512  * 0 on success
513  */
514 int bdisp_hw_alloc_filters(struct device *dev)
515 {
516         unsigned int i, size;
517         void *base;
518         dma_addr_t paddr;
519         DEFINE_DMA_ATTRS(attrs);
520
521         /* Allocate all the filters within a single memory page */
522         size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER);
523         dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
524         base = dma_alloc_attrs(dev, size, &paddr, GFP_KERNEL | GFP_DMA, &attrs);
525         if (!base)
526                 return -ENOMEM;
527
528         /* Setup filter addresses */
529         for (i = 0; i < NB_H_FILTER; i++) {
530                 bdisp_h_filter[i].min = bdisp_h_spec[i].min;
531                 bdisp_h_filter[i].max = bdisp_h_spec[i].max;
532                 memcpy(base, bdisp_h_spec[i].coef, BDISP_HF_NB);
533                 bdisp_h_filter[i].virt = base;
534                 bdisp_h_filter[i].paddr = paddr;
535                 base += BDISP_HF_NB;
536                 paddr += BDISP_HF_NB;
537         }
538
539         for (i = 0; i < NB_V_FILTER; i++) {
540                 bdisp_v_filter[i].min = bdisp_v_spec[i].min;
541                 bdisp_v_filter[i].max = bdisp_v_spec[i].max;
542                 memcpy(base, bdisp_v_spec[i].coef, BDISP_VF_NB);
543                 bdisp_v_filter[i].virt = base;
544                 bdisp_v_filter[i].paddr = paddr;
545                 base += BDISP_VF_NB;
546                 paddr += BDISP_VF_NB;
547         }
548
549         return 0;
550 }
551
552 /**
553  * bdisp_hw_get_hf_addr
554  * @inc:        resize increment
555  *
556  * Find the horizontal filter table that fits the resize increment
557  *
558  * RETURNS:
559  * table physical address
560  */
561 static dma_addr_t bdisp_hw_get_hf_addr(u16 inc)
562 {
563         unsigned int i;
564
565         for (i = NB_H_FILTER - 1; i > 0; i--)
566                 if ((bdisp_h_filter[i].min < inc) &&
567                     (inc <= bdisp_h_filter[i].max))
568                         break;
569
570         return bdisp_h_filter[i].paddr;
571 }
572
573 /**
574  * bdisp_hw_get_vf_addr
575  * @inc:        resize increment
576  *
577  * Find the vertical filter table that fits the resize increment
578  *
579  * RETURNS:
580  * table physical address
581  */
582 static dma_addr_t bdisp_hw_get_vf_addr(u16 inc)
583 {
584         unsigned int i;
585
586         for (i = NB_V_FILTER - 1; i > 0; i--)
587                 if ((bdisp_v_filter[i].min < inc) &&
588                     (inc <= bdisp_v_filter[i].max))
589                         break;
590
591         return bdisp_v_filter[i].paddr;
592 }
593
594 /**
595  * bdisp_hw_get_inc
596  * @from:       input size
597  * @to:         output size
598  * @inc:        resize increment in 6.10 format
599  *
600  * Computes the increment (inverse of scale) in 6.10 format
601  *
602  * RETURNS:
603  * 0 on success
604  */
605 static int bdisp_hw_get_inc(u32 from, u32 to, u16 *inc)
606 {
607         u32 tmp;
608
609         if (!to)
610                 return -EINVAL;
611
612         if (to == from) {
613                 *inc = 1 << 10;
614                 return 0;
615         }
616
617         tmp = (from << 10) / to;
618         if ((tmp > 0xFFFF) || (!tmp))
619                 /* overflow (downscale x 63) or too small (upscale x 1024) */
620                 return -EINVAL;
621
622         *inc = (u16)tmp;
623
624         return 0;
625 }
626
627 /**
628  * bdisp_hw_get_hv_inc
629  * @ctx:        device context
630  * @h_inc:      horizontal increment
631  * @v_inc:      vertical increment
632  *
633  * Computes the horizontal & vertical increments (inverse of scale)
634  *
635  * RETURNS:
636  * 0 on success
637  */
638 static int bdisp_hw_get_hv_inc(struct bdisp_ctx *ctx, u16 *h_inc, u16 *v_inc)
639 {
640         u32 src_w, src_h, dst_w, dst_h;
641
642         src_w = ctx->src.crop.width;
643         src_h = ctx->src.crop.height;
644         dst_w = ctx->dst.crop.width;
645         dst_h = ctx->dst.crop.height;
646
647         if (bdisp_hw_get_inc(src_w, dst_w, h_inc) ||
648             bdisp_hw_get_inc(src_h, dst_h, v_inc)) {
649                 dev_err(ctx->bdisp_dev->dev,
650                         "scale factors failed (%dx%d)->(%dx%d)\n",
651                         src_w, src_h, dst_w, dst_h);
652                 return -EINVAL;
653         }
654
655         return 0;
656 }
657
658 /**
659  * bdisp_hw_get_op_cfg
660  * @ctx:        device context
661  * @c:          operation configuration
662  *
663  * Check which blitter operations are expected and sets the scaling increments
664  *
665  * RETURNS:
666  * 0 on success
667  */
668 static int bdisp_hw_get_op_cfg(struct bdisp_ctx *ctx, struct bdisp_op_cfg *c)
669 {
670         struct device *dev = ctx->bdisp_dev->dev;
671         struct bdisp_frame *src = &ctx->src;
672         struct bdisp_frame *dst = &ctx->dst;
673
674         if (src->width > MAX_SRC_WIDTH * MAX_VERTICAL_STRIDES) {
675                 dev_err(dev, "Image width out of HW caps\n");
676                 return -EINVAL;
677         }
678
679         c->wide = src->width > MAX_SRC_WIDTH;
680
681         c->hflip = ctx->hflip;
682         c->vflip = ctx->vflip;
683
684         c->src_interlaced = (src->field == V4L2_FIELD_INTERLACED);
685
686         c->src_nbp = src->fmt->nb_planes;
687         c->src_yuv = (src->fmt->pixelformat == V4L2_PIX_FMT_NV12) ||
688                         (src->fmt->pixelformat == V4L2_PIX_FMT_YUV420);
689         c->src_420 = c->src_yuv;
690
691         c->dst_nbp = dst->fmt->nb_planes;
692         c->dst_yuv = (dst->fmt->pixelformat == V4L2_PIX_FMT_NV12) ||
693                         (dst->fmt->pixelformat == V4L2_PIX_FMT_YUV420);
694         c->dst_420 = c->dst_yuv;
695
696         c->cconv = (c->src_yuv != c->dst_yuv);
697
698         if (bdisp_hw_get_hv_inc(ctx, &c->h_inc, &c->v_inc)) {
699                 dev_err(dev, "Scale factor out of HW caps\n");
700                 return -EINVAL;
701         }
702
703         /* Deinterlacing adjustment : stretch a field to a frame */
704         if (c->src_interlaced)
705                 c->v_inc /= 2;
706
707         if ((c->h_inc != (1 << 10)) || (c->v_inc != (1 << 10)))
708                 c->scale = true;
709         else
710                 c->scale = false;
711
712         return 0;
713 }
714
715 /**
716  * bdisp_hw_color_format
717  * @pixelformat: v4l2 pixel format
718  *
719  * v4l2 to bdisp pixel format convert
720  *
721  * RETURNS:
722  * bdisp pixel format
723  */
724 static u32 bdisp_hw_color_format(u32 pixelformat)
725 {
726         u32 ret;
727
728         switch (pixelformat) {
729         case V4L2_PIX_FMT_YUV420:
730                 ret = (BDISP_YUV_3B << BLT_TTY_COL_SHIFT);
731                 break;
732         case V4L2_PIX_FMT_NV12:
733                 ret = (BDISP_NV12 << BLT_TTY_COL_SHIFT) | BLT_TTY_BIG_END;
734                 break;
735         case V4L2_PIX_FMT_RGB565:
736                 ret = (BDISP_RGB565 << BLT_TTY_COL_SHIFT);
737                 break;
738         case V4L2_PIX_FMT_XBGR32: /* This V4L format actually refers to xRGB */
739                 ret = (BDISP_XRGB8888 << BLT_TTY_COL_SHIFT);
740                 break;
741         case V4L2_PIX_FMT_RGB24:  /* RGB888 format */
742                 ret = (BDISP_RGB888 << BLT_TTY_COL_SHIFT) | BLT_TTY_BIG_END;
743                 break;
744         case V4L2_PIX_FMT_ABGR32: /* This V4L format actually refers to ARGB */
745
746         default:
747                 ret = (BDISP_ARGB8888 << BLT_TTY_COL_SHIFT) | BLT_TTY_ALPHA_R;
748                 break;
749         }
750
751         return ret;
752 }
753
754 /**
755  * bdisp_hw_build_node
756  * @ctx:        device context
757  * @cfg:        operation configuration
758  * @node:       node to be set
759  * @t_plan:     whether the node refers to a RGB/Y or a CbCr plane
760  * @src_x_offset: x offset in the source image
761  *
762  * Build a node
763  *
764  * RETURNS:
765  * None
766  */
767 static void bdisp_hw_build_node(struct bdisp_ctx *ctx,
768                                 struct bdisp_op_cfg *cfg,
769                                 struct bdisp_node *node,
770                                 enum bdisp_target_plan t_plan, int src_x_offset)
771 {
772         struct bdisp_frame *src = &ctx->src;
773         struct bdisp_frame *dst = &ctx->dst;
774         u16 h_inc, v_inc, yh_inc, yv_inc;
775         struct v4l2_rect src_rect = src->crop;
776         struct v4l2_rect dst_rect = dst->crop;
777         int dst_x_offset;
778         s32 dst_width = dst->crop.width;
779         u32 src_fmt, dst_fmt;
780         const u32 *ivmx;
781
782         dev_dbg(ctx->bdisp_dev->dev, "%s\n", __func__);
783
784         memset(node, 0, sizeof(*node));
785
786         /* Adjust src and dst areas wrt src_x_offset */
787         src_rect.left += src_x_offset;
788         src_rect.width -= src_x_offset;
789         src_rect.width = min_t(__s32, MAX_SRC_WIDTH, src_rect.width);
790
791         dst_x_offset = (src_x_offset * dst_width) / ctx->src.crop.width;
792         dst_rect.left += dst_x_offset;
793         dst_rect.width = (src_rect.width * dst_width) / ctx->src.crop.width;
794
795         /* General */
796         src_fmt = src->fmt->pixelformat;
797         dst_fmt = dst->fmt->pixelformat;
798
799         node->nip = 0;
800         node->cic = BLT_CIC_ALL_GRP;
801         node->ack = BLT_ACK_BYPASS_S2S3;
802
803         switch (cfg->src_nbp) {
804         case 1:
805                 /* Src2 = RGB / Src1 = Src3 = off */
806                 node->ins = BLT_INS_S1_OFF | BLT_INS_S2_MEM | BLT_INS_S3_OFF;
807                 break;
808         case 2:
809                 /* Src3 = Y
810                  * Src2 = CbCr or ColorFill if writing the Y plane
811                  * Src1 = off */
812                 node->ins = BLT_INS_S1_OFF | BLT_INS_S3_MEM;
813                 if (t_plan == BDISP_Y)
814                         node->ins |= BLT_INS_S2_CF;
815                 else
816                         node->ins |= BLT_INS_S2_MEM;
817                 break;
818         case 3:
819         default:
820                 /* Src3 = Y
821                  * Src2 = Cb or ColorFill if writing the Y plane
822                  * Src1 = Cr or ColorFill if writing the Y plane */
823                 node->ins = BLT_INS_S3_MEM;
824                 if (t_plan == BDISP_Y)
825                         node->ins |= BLT_INS_S2_CF | BLT_INS_S1_CF;
826                 else
827                         node->ins |= BLT_INS_S2_MEM | BLT_INS_S1_MEM;
828                 break;
829         }
830
831         /* Color convert */
832         node->ins |= cfg->cconv ? BLT_INS_IVMX : 0;
833         /* Scale needed if scaling OR 4:2:0 up/downsampling */
834         node->ins |= (cfg->scale || cfg->src_420 || cfg->dst_420) ?
835                         BLT_INS_SCALE : 0;
836
837         /* Target */
838         node->tba = (t_plan == BDISP_CBCR) ? dst->paddr[1] : dst->paddr[0];
839
840         node->tty = dst->bytesperline;
841         node->tty |= bdisp_hw_color_format(dst_fmt);
842         node->tty |= BLT_TTY_DITHER;
843         node->tty |= (t_plan == BDISP_CBCR) ? BLT_TTY_CHROMA : 0;
844         node->tty |= cfg->hflip ? BLT_TTY_HSO : 0;
845         node->tty |= cfg->vflip ? BLT_TTY_VSO : 0;
846
847         if (cfg->dst_420 && (t_plan == BDISP_CBCR)) {
848                 /* 420 chroma downsampling */
849                 dst_rect.height /= 2;
850                 dst_rect.width /= 2;
851                 dst_rect.left /= 2;
852                 dst_rect.top /= 2;
853                 dst_x_offset /= 2;
854                 dst_width /= 2;
855         }
856
857         node->txy = cfg->vflip ? (dst_rect.height - 1) : dst_rect.top;
858         node->txy <<= 16;
859         node->txy |= cfg->hflip ? (dst_width - dst_x_offset - 1) :
860                         dst_rect.left;
861
862         node->tsz = dst_rect.height << 16 | dst_rect.width;
863
864         if (cfg->src_interlaced) {
865                 /* handle only the top field which is half height of a frame */
866                 src_rect.top /= 2;
867                 src_rect.height /= 2;
868         }
869
870         if (cfg->src_nbp == 1) {
871                 /* Src 2 : RGB */
872                 node->s2ba = src->paddr[0];
873
874                 node->s2ty = src->bytesperline;
875                 if (cfg->src_interlaced)
876                         node->s2ty *= 2;
877
878                 node->s2ty |= bdisp_hw_color_format(src_fmt);
879
880                 node->s2xy = src_rect.top << 16 | src_rect.left;
881                 node->s2sz = src_rect.height << 16 | src_rect.width;
882         } else {
883                 /* Src 2 : Cb or CbCr */
884                 if (cfg->src_420) {
885                         /* 420 chroma upsampling */
886                         src_rect.top /= 2;
887                         src_rect.left /= 2;
888                         src_rect.width /= 2;
889                         src_rect.height /= 2;
890                 }
891
892                 node->s2ba = src->paddr[1];
893
894                 node->s2ty = src->bytesperline;
895                 if (cfg->src_nbp == 3)
896                         node->s2ty /= 2;
897                 if (cfg->src_interlaced)
898                         node->s2ty *= 2;
899
900                 node->s2ty |= bdisp_hw_color_format(src_fmt);
901
902                 node->s2xy = src_rect.top << 16 | src_rect.left;
903                 node->s2sz = src_rect.height << 16 | src_rect.width;
904
905                 if (cfg->src_nbp == 3) {
906                         /* Src 1 : Cr */
907                         node->s1ba = src->paddr[2];
908
909                         node->s1ty = node->s2ty;
910                         node->s1xy = node->s2xy;
911                 }
912
913                 /* Src 3 : Y */
914                 node->s3ba = src->paddr[0];
915
916                 node->s3ty = src->bytesperline;
917                 if (cfg->src_interlaced)
918                         node->s3ty *= 2;
919                 node->s3ty |= bdisp_hw_color_format(src_fmt);
920
921                 if ((t_plan != BDISP_CBCR) && cfg->src_420) {
922                         /* No chroma upsampling for output RGB / Y plane */
923                         node->s3xy = node->s2xy * 2;
924                         node->s3sz = node->s2sz * 2;
925                 } else {
926                         /* No need to read Y (Src3) when writing Chroma */
927                         node->s3ty |= BLT_S3TY_BLANK_ACC;
928                         node->s3xy = node->s2xy;
929                         node->s3sz = node->s2sz;
930                 }
931         }
932
933         /* Resize (scale OR 4:2:0: chroma up/downsampling) */
934         if (node->ins & BLT_INS_SCALE) {
935                 /* no need to compute Y when writing CbCr from RGB input */
936                 bool skip_y = (t_plan == BDISP_CBCR) && !cfg->src_yuv;
937
938                 /* FCTL */
939                 if (cfg->scale) {
940                         node->fctl = BLT_FCTL_HV_SCALE;
941                         if (!skip_y)
942                                 node->fctl |= BLT_FCTL_Y_HV_SCALE;
943                 } else {
944                         node->fctl = BLT_FCTL_HV_SAMPLE;
945                         if (!skip_y)
946                                 node->fctl |= BLT_FCTL_Y_HV_SAMPLE;
947                 }
948
949                 /* RSF - Chroma may need to be up/downsampled */
950                 h_inc = cfg->h_inc;
951                 v_inc = cfg->v_inc;
952                 if (!cfg->src_420 && cfg->dst_420 && (t_plan == BDISP_CBCR)) {
953                         /* RGB to 4:2:0 for Chroma: downsample */
954                         h_inc *= 2;
955                         v_inc *= 2;
956                 } else if (cfg->src_420 && !cfg->dst_420) {
957                         /* 4:2:0: to RGB: upsample*/
958                         h_inc /= 2;
959                         v_inc /= 2;
960                 }
961                 node->rsf = v_inc << 16 | h_inc;
962
963                 /* RZI */
964                 node->rzi = BLT_RZI_DEFAULT;
965
966                 /* Filter table physical addr */
967                 node->hfp = bdisp_hw_get_hf_addr(h_inc);
968                 node->vfp = bdisp_hw_get_vf_addr(v_inc);
969
970                 /* Y version */
971                 if (!skip_y) {
972                         yh_inc = cfg->h_inc;
973                         yv_inc = cfg->v_inc;
974
975                         node->y_rsf = yv_inc << 16 | yh_inc;
976                         node->y_rzi = BLT_RZI_DEFAULT;
977                         node->y_hfp = bdisp_hw_get_hf_addr(yh_inc);
978                         node->y_vfp = bdisp_hw_get_vf_addr(yv_inc);
979                 }
980         }
981
982         /* Versatile matrix for RGB / YUV conversion */
983         if (cfg->cconv) {
984                 ivmx = cfg->src_yuv ? bdisp_yuv_to_rgb : bdisp_rgb_to_yuv;
985
986                 node->ivmx0 = ivmx[0];
987                 node->ivmx1 = ivmx[1];
988                 node->ivmx2 = ivmx[2];
989                 node->ivmx3 = ivmx[3];
990         }
991 }
992
993 /**
994  * bdisp_hw_build_all_nodes
995  * @ctx:        device context
996  *
997  * Build all the nodes for the blitter operation
998  *
999  * RETURNS:
1000  * 0 on success
1001  */
1002 static int bdisp_hw_build_all_nodes(struct bdisp_ctx *ctx)
1003 {
1004         struct bdisp_op_cfg cfg;
1005         unsigned int i, nid = 0;
1006         int src_x_offset = 0;
1007
1008         for (i = 0; i < MAX_NB_NODE; i++)
1009                 if (!ctx->node[i]) {
1010                         dev_err(ctx->bdisp_dev->dev, "node %d is null\n", i);
1011                         return -EINVAL;
1012                 }
1013
1014         /* Get configuration (scale, flip, ...) */
1015         if (bdisp_hw_get_op_cfg(ctx, &cfg))
1016                 return -EINVAL;
1017
1018         /* Split source in vertical strides (HW constraint) */
1019         for (i = 0; i < MAX_VERTICAL_STRIDES; i++) {
1020                 /* Build RGB/Y node and link it to the previous node */
1021                 bdisp_hw_build_node(ctx, &cfg, ctx->node[nid],
1022                                     cfg.dst_nbp == 1 ? BDISP_RGB : BDISP_Y,
1023                                     src_x_offset);
1024                 if (nid)
1025                         ctx->node[nid - 1]->nip = ctx->node_paddr[nid];
1026                 nid++;
1027
1028                 /* Build additional Cb(Cr) node, link it to the previous one */
1029                 if (cfg.dst_nbp > 1) {
1030                         bdisp_hw_build_node(ctx, &cfg, ctx->node[nid],
1031                                             BDISP_CBCR, src_x_offset);
1032                         ctx->node[nid - 1]->nip = ctx->node_paddr[nid];
1033                         nid++;
1034                 }
1035
1036                 /* Next stride until full width covered */
1037                 src_x_offset += MAX_SRC_WIDTH;
1038                 if (src_x_offset >= ctx->src.crop.width)
1039                         break;
1040         }
1041
1042         /* Mark last node as the last */
1043         ctx->node[nid - 1]->nip = 0;
1044
1045         return 0;
1046 }
1047
1048 /**
1049  * bdisp_hw_save_request
1050  * @ctx:        device context
1051  *
1052  * Save a copy of the request and of the built nodes
1053  *
1054  * RETURNS:
1055  * None
1056  */
1057 static void bdisp_hw_save_request(struct bdisp_ctx *ctx)
1058 {
1059         struct bdisp_node **copy_node = ctx->bdisp_dev->dbg.copy_node;
1060         struct bdisp_request *request = &ctx->bdisp_dev->dbg.copy_request;
1061         struct bdisp_node **node = ctx->node;
1062         int i;
1063
1064         /* Request copy */
1065         request->src = ctx->src;
1066         request->dst = ctx->dst;
1067         request->hflip = ctx->hflip;
1068         request->vflip = ctx->vflip;
1069         request->nb_req++;
1070
1071         /* Nodes copy */
1072         for (i = 0; i < MAX_NB_NODE; i++) {
1073                 /* Allocate memory if not done yet */
1074                 if (!copy_node[i]) {
1075                         copy_node[i] = devm_kzalloc(ctx->bdisp_dev->dev,
1076                                                     sizeof(*copy_node[i]),
1077                                                     GFP_KERNEL);
1078                         if (!copy_node[i])
1079                                 return;
1080                 }
1081                 *copy_node[i] = *node[i];
1082         }
1083 }
1084
1085 /**
1086  * bdisp_hw_update
1087  * @ctx:        device context
1088  *
1089  * Send the request to the HW
1090  *
1091  * RETURNS:
1092  * 0 on success
1093  */
1094 int bdisp_hw_update(struct bdisp_ctx *ctx)
1095 {
1096         int ret;
1097         struct bdisp_dev *bdisp = ctx->bdisp_dev;
1098         struct device *dev = bdisp->dev;
1099         unsigned int node_id;
1100
1101         dev_dbg(dev, "%s\n", __func__);
1102
1103         /* build nodes */
1104         ret = bdisp_hw_build_all_nodes(ctx);
1105         if (ret) {
1106                 dev_err(dev, "cannot build nodes (%d)\n", ret);
1107                 return ret;
1108         }
1109
1110         /* Save a copy of the request */
1111         bdisp_hw_save_request(ctx);
1112
1113         /* Configure interrupt to 'Last Node Reached for AQ1' */
1114         writel(BLT_AQ1_CTL_CFG, bdisp->regs + BLT_AQ1_CTL);
1115         writel(BLT_ITS_AQ1_LNA, bdisp->regs + BLT_ITM0);
1116
1117         /* Write first node addr */
1118         writel(ctx->node_paddr[0], bdisp->regs + BLT_AQ1_IP);
1119
1120         /* Find and write last node addr : this starts the HW processing */
1121         for (node_id = 0; node_id < MAX_NB_NODE - 1; node_id++) {
1122                 if (!ctx->node[node_id]->nip)
1123                         break;
1124         }
1125         writel(ctx->node_paddr[node_id], bdisp->regs + BLT_AQ1_LNA);
1126
1127         return 0;
1128 }