1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "drm_hal_gfx.h"
20 #include <linux/module.h>
21 #include "hifb_vou_drv.h"
22 #include "hifb_vou_graphics.h"
23 #include "hifb_main.h"
24 #include "hi_drm_func_ext.h"
25
26 #define hal_gfx_check_open(layer_param) do { \
27 if (layer_param == NULL || layer_param->open_cnt <= 0) { \
28 drm_hal_err("layer not opened!\n"); \
29 return -1; \
30 } \
31 } while (0)
32
33 #define hal_gfx_check_ptr(ptr) do { \
34 if (ptr == NULL) { \
35 drm_hal_err("null ptr!\n"); \
36 return -1; \
37 } \
38 } while (0)
39
40 struct gfx_layer_params {
41 unsigned int layer_id;
42 int open_cnt;
43 drm_hal_gfx_cb gfx_cb;
44 };
45
46 struct hal_gfx_dev_params {
47 hifb_drv_ops gfx_api;
48 struct gfx_layer_params layer_param[DRM_HAL_GFX_MAX];
49 };
50
51 static struct drm_hal_gfx_dev gfx_dev = {0};
52
gfx_get_api(void)53 static hifb_drv_ops *gfx_get_api(void)
54 {
55 if (gfx_dev.params == NULL) {
56 return NULL;
57 }
58 return &(((struct hal_gfx_dev_params *)gfx_dev.params)->gfx_api);
59 }
60
gfx_get_layer_param(enum drm_hal_gfx_layer layer)61 static struct gfx_layer_params *gfx_get_layer_param(enum drm_hal_gfx_layer layer)
62 {
63 int ret;
64
65 if (layer >= DRM_HAL_GFX_MAX) {
66 return NULL;
67 }
68 /* has init */
69 if (gfx_dev.params != NULL) {
70 return &(((struct hal_gfx_dev_params *)gfx_dev.params)->layer_param[layer]);
71 }
72
73 gfx_dev.params = kzalloc(sizeof(struct hal_gfx_dev_params), GFP_KERNEL);
74 if (gfx_dev.params == NULL) {
75 drm_hal_err("kzalloc err!\n");
76 return NULL;
77 }
78
79 hifb_drv_get_ops(gfx_get_api());
80 /*
81 * can not init here, because hifb ko has inited
82 * gfx_api->hifb_drv_init()
83 */
84 ret = osal_spin_lock_init(&(gfx_dev.lock));
85 if (ret < 0) {
86 drm_hal_err("spinlock init failed!\n");
87 kfree(gfx_dev.params);
88 gfx_dev.params = NULL;
89 return NULL;
90 }
91
92 return &(((struct hal_gfx_dev_params *)gfx_dev.params)->layer_param[layer]);
93 }
94
gfx_layer_translate(enum drm_hal_gfx_layer layer)95 static int gfx_layer_translate(enum drm_hal_gfx_layer layer)
96 {
97 switch (layer) {
98 case DRM_HAL_GFX_G0:
99 return 0;
100 case DRM_HAL_GFX_G1:
101 return 1;
102 case DRM_HAL_GFX_G3:
103 return 2; /* 2:G3 */
104 default:
105 drm_hal_err("invalid layer id: %u\n", layer);
106 return -1;
107 }
108 return -1;
109 }
110
drm_hal_gfx_deinit(void)111 static void drm_hal_gfx_deinit(void)
112 {
113 /*
114 * can not deinit here, because hifb ko has deinited
115 * gfx_api->hifb_drv_deinit()
116 */
117 if (gfx_dev.params != NULL) {
118 kfree(gfx_dev.params);
119 gfx_dev.params = NULL;
120 }
121 osal_spin_lock_destroy(&(gfx_dev.lock));
122 return;
123 }
124
drm_hal_gfx_open(enum drm_hal_gfx_layer layer)125 static int drm_hal_gfx_open(enum drm_hal_gfx_layer layer)
126 {
127 unsigned long lock_flag;
128 struct gfx_layer_params *param = gfx_get_layer_param(layer);
129 int layer_id;
130 hal_gfx_check_ptr(param);
131
132 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
133 if (param->open_cnt > 0) {
134 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
135 drm_hal_info("already opened, cnt=%d\n", param->open_cnt);
136 return 0;
137 }
138
139 layer_id = gfx_layer_translate(layer);
140 if (layer_id == -1) {
141 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
142 return -1;
143 }
144
145 param->layer_id = layer_id;
146 param->open_cnt++;
147 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
148 return 0;
149 }
150
drm_hal_gfx_close(enum drm_hal_gfx_layer layer)151 static int drm_hal_gfx_close(enum drm_hal_gfx_layer layer)
152 {
153 unsigned long lock_flag;
154 struct gfx_layer_params *param = gfx_get_layer_param(layer);
155 hal_gfx_check_ptr(param);
156
157 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
158 if (param->open_cnt <= 0) {
159 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
160 drm_hal_info("already closed, cnt=%d\n", param->open_cnt);
161 return 0;
162 }
163
164 param->open_cnt--;
165 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
166 return 0;
167 }
168
169
gfx_callback(hi_u32 layer_id,hifb_main_intf_type type,void * para)170 static int gfx_callback(hi_u32 layer_id, hifb_main_intf_type type, void *para)
171 {
172 int ret = 0;
173 int i;
174 unsigned long lock_flag;
175 enum drm_hal_gfx_layer layer;
176 struct hal_gfx_dev_params *dev_param = (struct hal_gfx_dev_params *)gfx_dev.params;
177 hal_gfx_check_ptr(dev_param);
178
179 switch (layer_id) {
180 case 0:
181 layer = DRM_HAL_GFX_G0;
182 break;
183 case 1:
184 layer = DRM_HAL_GFX_G1;
185 break;
186 case 2:
187 layer = DRM_HAL_GFX_G3;
188 break;
189 default:
190 return -1;
191 }
192 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
193 for (i = 0; i < DRM_HAL_GFX_MAX; i++) {
194 if ((dev_param->layer_param[i].layer_id == layer_id) &&
195 (dev_param->layer_param[i].open_cnt > 0) &&
196 (dev_param->layer_param[i].gfx_cb != NULL)) {
197 ret = dev_param->layer_param[i].gfx_cb(layer, DRM_HAL_GFX_CB_INTR_100, NULL);
198 break;
199 }
200 }
201
202 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
203 return ret;
204 }
205
drm_hal_gfx_enable(enum drm_hal_gfx_layer layer)206 static int drm_hal_gfx_enable(enum drm_hal_gfx_layer layer)
207 {
208 int ret;
209 unsigned long lock_flag;
210 struct gfx_layer_params *param = gfx_get_layer_param(layer);
211 hifb_drv_ops *gfx_api = gfx_get_api();
212 hal_gfx_check_ptr(param);
213 hal_gfx_check_ptr(gfx_api);
214
215 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
216 if (param->open_cnt <= 0) {
217 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
218 drm_hal_err("layer not opened!\n");
219 return -1;
220 }
221
222 /* this api should be called after vo enable, so we put it here */
223 ret = vou_graphics_init();
224 if (ret != 0) {
225 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
226 drm_hal_err("err, ret=%#x\n", ret);
227 return ret;
228 }
229
230 ret = gfx_api->hifb_open_layer(param->layer_id);
231 if (ret != 0) {
232 drm_hal_err("err, ret=%#x, id=%u\n", ret, param->layer_id);
233 goto err_vou_gfx_deinit;
234 }
235
236 ret = gfx_api->hifb_drv_layer_default_setting(param->layer_id);
237 if (ret != 0) {
238 drm_hal_err("err, ret=%#x, id=%u\n", ret, param->layer_id);
239 goto err_close_layer;
240 }
241
242 hifb_main_reg_callback(param->layer_id, HIFB_INTTYPE_VO, gfx_callback);
243
244 ret = gfx_api->hifb_drv_enable_layer(param->layer_id, HI_TRUE);
245 if (ret != 0) {
246 drm_hal_err("err, ret=%#x\n", ret);
247 goto err_unreg_callback;
248 }
249 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
250 return 0;
251
252 err_unreg_callback:
253 hifb_main_reg_callback(param->layer_id, HIFB_INTTYPE_VO, HI_NULL);
254 err_close_layer:
255 (void)gfx_api->hifb_close_layer(param->layer_id);
256 err_vou_gfx_deinit:
257 (void)vou_graphics_deinit();
258 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
259 return ret;
260 }
261
drm_hal_gfx_disable(enum drm_hal_gfx_layer layer)262 static int drm_hal_gfx_disable(enum drm_hal_gfx_layer layer)
263 {
264 int ret;
265 unsigned long lock_flag;
266 struct gfx_layer_params *param = gfx_get_layer_param(layer);
267 hifb_drv_ops *gfx_api = gfx_get_api();
268 hal_gfx_check_ptr(param);
269 hal_gfx_check_ptr(gfx_api);
270
271 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
272 if (param->open_cnt <= 0) {
273 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
274 drm_hal_err("layer not opened!\n");
275 return -1;
276 }
277
278 ret = gfx_api->hifb_drv_enable_layer(param->layer_id, HI_FALSE);
279 if (ret != 0) {
280 drm_hal_err("err, ret=%#x\n", ret);
281 }
282
283 /* to be optimizing */
284 hifb_main_reg_callback(param->layer_id, HIFB_INTTYPE_VO, HI_NULL);
285
286 ret = gfx_api->hifb_close_layer(param->layer_id);
287 if (ret != 0) {
288 drm_hal_err("err, ret=%#x\n", ret);
289 }
290
291 ret = vou_graphics_deinit();
292 if (ret != 0) {
293 drm_hal_err("err, ret=%#x\n", ret);
294 }
295
296 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
297 return ret;
298 }
299
drm_hal_gfx_get_attr(enum drm_hal_gfx_layer layer,enum drm_hal_gfx_attr_type type,const void * param)300 static int drm_hal_gfx_get_attr(enum drm_hal_gfx_layer layer, enum drm_hal_gfx_attr_type type, const void *param)
301 {
302 (void)layer;
303 (void)type;
304 (void)param;
305 return 0;
306 }
307
gfx_set_size(unsigned int id,struct drm_hal_rect * out_rect)308 static int gfx_set_size(unsigned int id, struct drm_hal_rect *out_rect)
309 {
310 HIFB_RECT in = {0};
311 HIFB_RECT out;
312 hifb_drv_ops *gfx_api = gfx_get_api();
313
314 hal_gfx_check_ptr(gfx_api);
315
316 out.x = out_rect->x;
317 out.y = out_rect->y;
318 out.w = out_rect->w;
319 out.h = out_rect->h;
320
321 return gfx_api->hifb_drv_set_layer_rect(id, &in, &out);
322 }
323
gfx_set_alpha(unsigned int id,unsigned int alpha)324 static int gfx_set_alpha(unsigned int id, unsigned int alpha)
325 {
326 HIFB_ALPHA_S hifb_alpha = {0};
327 hifb_drv_ops *gfx_api = gfx_get_api();
328
329 hal_gfx_check_ptr(gfx_api);
330
331 return gfx_api->hifb_drv_set_layer_alpha(id, hifb_alpha);
332 }
333
gfx_set_zpos(unsigned int id,unsigned int zpos)334 static int gfx_set_zpos(unsigned int id, unsigned int zpos)
335 {
336 (void)id;
337 (void)zpos;
338 drm_hal_err("unsupported yet!\n");
339 return -1;
340 }
341
gfx_set_format(unsigned int id,enum drm_hal_color_fmt fmt)342 static int gfx_set_format(unsigned int id, enum drm_hal_color_fmt fmt)
343 {
344 HIFB_COLOR_FMT_E hifb_fmt;
345 hifb_drv_ops *gfx_api = gfx_get_api();
346
347 hal_gfx_check_ptr(gfx_api);
348 hal_gfx_check_ptr(gfx_api->hifb_drv_set_layer_data_fmt);
349
350 switch (fmt) {
351 case DRM_HAL_FMT_ARGB8888:
352 hifb_fmt = DRM_HAL_FMT_ARGB8888;
353 break;
354 case DRM_HAL_FMT_ARGB1555:
355 hifb_fmt = DRM_HAL_FMT_ARGB1555;
356 break;
357 default:
358 hifb_fmt = DRM_HAL_FMT_ARGB8888;
359 break;
360 }
361
362 return gfx_api->hifb_drv_set_layer_data_fmt(id, hifb_fmt);
363 }
364
gfx_set_buffer(unsigned int id,unsigned long long addr)365 static int gfx_set_buffer(unsigned int id, unsigned long long addr)
366 {
367 hifb_drv_ops *gfx_api = gfx_get_api();
368
369 hal_gfx_check_ptr(gfx_api);
370
371 return gfx_api->hifb_drv_set_layer_addr(id, addr);
372 }
373
gfx_set_stride(unsigned int id,unsigned int stride)374 static int gfx_set_stride(unsigned int id, unsigned int stride)
375 {
376 hifb_drv_ops *gfx_api = gfx_get_api();
377 hal_gfx_check_ptr(gfx_api);
378 return gfx_api->hifb_drv_set_layer_stride(id, stride);
379 }
380
drm_hal_gfx_set_attr(enum drm_hal_gfx_layer layer,enum drm_hal_gfx_attr_type type,const void * param)381 static int drm_hal_gfx_set_attr(enum drm_hal_gfx_layer layer, enum drm_hal_gfx_attr_type type, const void *param)
382 {
383 int ret;
384 unsigned long lock_flag;
385 struct gfx_layer_params *layer_param = gfx_get_layer_param(layer);
386 hifb_drv_ops *gfx_api = gfx_get_api();
387
388 hal_gfx_check_ptr(layer_param);
389 hal_gfx_check_ptr(gfx_api);
390
391 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
392 if (layer_param->open_cnt <= 0) {
393 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
394 drm_hal_err("layer not opened!\n");
395 return -1;
396 }
397
398 switch (type) {
399 case DRM_HAL_GFX_ATTR_SIZE:
400 ret = gfx_set_size(layer_param->layer_id, (struct drm_hal_rect *)param);
401 break;
402 case DRM_HAL_GFX_ATTR_ALPHA:
403 ret = gfx_set_alpha(layer_param->layer_id, *(unsigned int *)param);
404 break;
405 case DRM_HAL_GFX_ATTR_ZPOS:
406 ret = gfx_set_zpos(layer_param->layer_id, *(unsigned int *)param);
407 break;
408 case DRM_HAL_GFX_ATTR_FORMAT:
409 ret = gfx_set_format(layer_param->layer_id, *(enum drm_hal_color_fmt *)param);
410 break;
411 case DRM_HAL_GFX_ATTR_STRIDE:
412 ret = gfx_set_stride(layer_param->layer_id, *(unsigned int *)param);
413 break;
414 case DRM_HAL_GFX_ATTR_BUFFER:
415 ret = gfx_set_buffer(layer_param->layer_id, *(unsigned long long *)param);
416 break;
417 default:
418 drm_hal_err("attr type %d not support!\n", type);
419 ret = -1;
420 }
421
422 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
423 return ret;
424 }
425
drm_hal_gfx_register_cb(enum drm_hal_gfx_layer layer,enum drm_hal_gfx_cb_type type,drm_hal_gfx_cb cb)426 static int drm_hal_gfx_register_cb(enum drm_hal_gfx_layer layer, enum drm_hal_gfx_cb_type type, drm_hal_gfx_cb cb)
427 {
428 unsigned long lock_flag;
429 struct gfx_layer_params *param = gfx_get_layer_param(layer);
430 hifb_drv_ops *gfx_api = gfx_get_api();
431
432 hal_gfx_check_ptr(param);
433 hal_gfx_check_ptr(gfx_api);
434
435 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
436 if (param->open_cnt <= 0) {
437 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
438 drm_hal_err("layer not opened!\n");
439 return -1;
440 }
441
442 param->gfx_cb = cb;
443 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
444 return 0;
445 }
446
drm_hal_disp_unregister_cb(enum drm_hal_gfx_layer layer,enum drm_hal_gfx_cb_type type)447 static int drm_hal_disp_unregister_cb(enum drm_hal_gfx_layer layer, enum drm_hal_gfx_cb_type type)
448 {
449 unsigned long lock_flag;
450 struct gfx_layer_params *param = gfx_get_layer_param(layer);
451 hifb_drv_ops *gfx_api = gfx_get_api();
452
453 hal_gfx_check_ptr(param);
454 hal_gfx_check_ptr(gfx_api);
455
456 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
457 if (param->open_cnt <= 0) {
458 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
459 drm_hal_err("layer not opened!\n");
460 return -1;
461 }
462
463 param->gfx_cb = NULL;
464 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
465 return 0;
466 }
467
drm_hal_gfx_refresh(enum drm_hal_gfx_layer layer)468 static int drm_hal_gfx_refresh(enum drm_hal_gfx_layer layer)
469 {
470 int ret;
471 unsigned long lock_flag;
472 struct gfx_layer_params *param = gfx_get_layer_param(layer);
473 hifb_drv_ops *gfx_api = gfx_get_api();
474
475 hal_gfx_check_ptr(param);
476 hal_gfx_check_ptr(gfx_api);
477
478 osal_spin_lock_irqsave(&(gfx_dev.lock), &lock_flag);
479 if (param->open_cnt <= 0) {
480 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
481 drm_hal_err("layer not opened!\n");
482 return -1;
483 }
484
485 ret = gfx_api->hifb_drv_updata_layer_reg(param->layer_id);
486 if (ret != 0) {
487 drm_hal_err("err, ret=%#x\n", ret);
488 }
489 osal_spin_unlock_irqrestore(&(gfx_dev.lock), &lock_flag);
490 return 0;
491 }
492
drm_hal_gfx_dev_register(hi_void)493 hi_void drm_hal_gfx_dev_register(hi_void)
494 {
495 hi_drm_export_func *drm_ext_func = HI_NULL;
496 drm_ext_func = drm_export_func_register();
497 if (drm_ext_func == HI_NULL) {
498 drm_hal_err("err:drm_ext_func is NULL!\n");
499 return;
500 }
501 drm_ext_func->gfx_func = &gfx_dev;
502 gfx_dev.deinit = drm_hal_gfx_deinit;
503 gfx_dev.open = drm_hal_gfx_open;
504 gfx_dev.close = drm_hal_gfx_close;
505 gfx_dev.enable = drm_hal_gfx_enable;
506 gfx_dev.disable = drm_hal_gfx_disable;
507 gfx_dev.get_attr = drm_hal_gfx_get_attr;
508 gfx_dev.set_attr = drm_hal_gfx_set_attr;
509 gfx_dev.register_cb = drm_hal_gfx_register_cb;
510 gfx_dev.unregister_cb = drm_hal_disp_unregister_cb;
511 gfx_dev.refresh = drm_hal_gfx_refresh;
512
513 return;
514 }
515
drm_hal_gfx_dev_unregister(hi_void)516 hi_void drm_hal_gfx_dev_unregister(hi_void)
517 {
518 hi_drm_export_func *drm_ext_func = HI_NULL;
519 drm_ext_func = drm_export_func_register();
520 if (drm_ext_func == HI_NULL) {
521 drm_hal_err("err:drm_ext_func is NULL!\n");
522 return;
523 }
524
525 gfx_dev.deinit = NULL;
526 gfx_dev.open = NULL;
527 gfx_dev.close = NULL;
528 gfx_dev.enable = NULL;
529 gfx_dev.disable = NULL;
530 gfx_dev.get_attr = NULL;
531 gfx_dev.set_attr = NULL;
532 gfx_dev.register_cb = NULL;
533 gfx_dev.unregister_cb = NULL;
534 gfx_dev.refresh = NULL;
535 drm_ext_func->gfx_func = NULL;
536
537 return;
538 }
539
540