amlogic: drm: don't call irq in crtc init stage
[platform/kernel/linux-amlogic.git] / drivers / amlogic / drm / meson_vpu.c
1 /*
2  * drivers/amlogic/drm/meson_vpu.c
3  *
4  * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17
18 #include <drm/drmP.h>
19 #include <drm/drm_plane.h>
20 #include <drm/drm_atomic.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_fb_cma_helper.h>
23 #include <drm/drm_gem_cma_helper.h>
24
25 #include <linux/platform_device.h>
26 #include <linux/of_device.h>
27 #include <linux/of.h>
28 #include <linux/component.h>
29 #include <linux/of_reserved_mem.h>
30 #include <linux/dma-contiguous.h>
31 #include <linux/cma.h>
32 #ifdef CONFIG_DRM_MESON_USE_ION
33 #include <ion/ion_priv.h>
34 #endif
35
36 /* Amlogic Headers */
37 #include <linux/amlogic/media/vout/vout_notify.h>
38 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
39 #include <linux/amlogic/media/amvecm/amvecm.h>
40 #endif
41 #include "osd.h"
42 #include "osd_drm.h"
43 #ifdef CONFIG_DRM_MESON_USE_ION
44 #include "meson_fb.h"
45 #endif
46 #include "meson_vpu.h"
47 #include "meson_plane.h"
48 #include "meson_crtc.h"
49 #include "meson_vpu_pipeline.h"
50
51 struct vpu_device_data_s {
52         enum cpuid_type_e cpu_id;
53         enum osd_ver_e osd_ver;
54         enum osd_afbc_e afbc_type;
55         u8 osd_count;
56         u8 has_deband;
57         u8 has_lut;
58         u8 has_rdma;
59         u8 osd_fifo_len;
60         u32 vpp_fifo_len;
61         u32 dummy_data;
62         u32 has_viu2;
63         u32 viu1_osd_count;
64         struct clk *vpu_clkc;
65 };
66
67 static struct am_vout_mode am_vout_modes[] = {
68         { "1080p60hz", VMODE_HDMI, 1920, 1080, 60, 0},
69         { "1080p30hz", VMODE_HDMI, 1920, 1080, 30, 0},
70         { "1080p50hz", VMODE_HDMI, 1920, 1080, 50, 0},
71         { "1080p25hz", VMODE_HDMI, 1920, 1080, 25, 0},
72         { "1080p24hz", VMODE_HDMI, 1920, 1080, 24, 0},
73         { "2160p30hz", VMODE_HDMI, 3840, 2160, 30, 0},
74         { "2160p60hz", VMODE_HDMI, 3840, 2160, 60, 0},
75         { "2160p50hz", VMODE_HDMI, 3840, 2160, 50, 0},
76         { "2160p25hz", VMODE_HDMI, 3840, 2160, 25, 0},
77         { "2160p24hz", VMODE_HDMI, 3840, 2160, 24, 0},
78         { "1080i60hz", VMODE_HDMI, 1920, 1080, 60, DRM_MODE_FLAG_INTERLACE},
79         { "1080i50hz", VMODE_HDMI, 1920, 1080, 50, DRM_MODE_FLAG_INTERLACE},
80         { "720p60hz", VMODE_HDMI, 1280, 720, 60, 0},
81         { "720p50hz", VMODE_HDMI, 1280, 720, 50, 0},
82         { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
83         { "480i60hz", VMODE_HDMI, 720, 480, 60, DRM_MODE_FLAG_INTERLACE},
84         { "576p50hz", VMODE_HDMI, 720, 576, 50, 0},
85         { "576i50hz", VMODE_HDMI, 720, 576, 50, DRM_MODE_FLAG_INTERLACE},
86         { "480p60hz", VMODE_HDMI, 720, 480, 60, 0},
87 };
88
89
90 static struct osd_device_data_s osd_gxbb = {
91         .cpu_id = __MESON_CPU_MAJOR_ID_GXBB,
92         .osd_ver = OSD_NORMAL,
93         .afbc_type = NO_AFBC,
94         .osd_count = 2,
95         .has_deband = 0,
96         .has_lut = 0,
97         .has_rdma = 1,
98         .has_dolby_vision = 0,
99         .osd_fifo_len = 32,
100         .vpp_fifo_len = 0x77f,
101         .dummy_data = 0x00808000,
102         .has_viu2 = 0,
103 };
104
105 static struct osd_device_data_s osd_gxl = {
106         .cpu_id = __MESON_CPU_MAJOR_ID_GXL,
107         .osd_ver = OSD_NORMAL,
108         .afbc_type = NO_AFBC,
109         .osd_count = 2,
110         .has_deband = 0,
111         .has_lut = 0,
112         .has_rdma = 1,
113         .has_dolby_vision = 0,
114         .osd_fifo_len = 32,
115         .vpp_fifo_len = 0x77f,
116         .dummy_data = 0x00808000,
117         .has_viu2 = 0,
118 };
119
120 static struct osd_device_data_s osd_gxm = {
121         .cpu_id = __MESON_CPU_MAJOR_ID_GXM,
122         .osd_ver = OSD_NORMAL,
123         .afbc_type = MESON_AFBC,
124         .osd_count = 2,
125         .has_deband = 0,
126         .has_lut = 0,
127         .has_rdma = 1,
128         .has_dolby_vision = 0,
129         .osd_fifo_len = 32,
130         .vpp_fifo_len = 0xfff,
131         .dummy_data = 0x00202000,/* dummy data is different */
132         .has_viu2 = 0,
133 };
134
135 static struct osd_device_data_s osd_txl = {
136         .cpu_id = __MESON_CPU_MAJOR_ID_TXL,
137         .osd_ver = OSD_NORMAL,
138         .afbc_type = NO_AFBC,
139         .osd_count = 2,
140         .has_deband = 0,
141         .has_lut = 0,
142         .has_rdma = 1,
143         .has_dolby_vision = 0,
144         .osd_fifo_len = 64,
145         .vpp_fifo_len = 0x77f,
146         .dummy_data = 0x00808000,
147         .has_viu2 = 0,
148 };
149
150 static struct osd_device_data_s osd_txlx = {
151         .cpu_id = __MESON_CPU_MAJOR_ID_TXLX,
152         .osd_ver = OSD_NORMAL,
153         .afbc_type = NO_AFBC,
154         .osd_count = 2,
155         .has_deband = 1,
156         .has_lut = 1,
157         .has_rdma = 1,
158         .has_dolby_vision = 1,
159         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
160         .vpp_fifo_len = 0x77f,
161         .dummy_data = 0x00808000,
162         .has_viu2 = 0,
163 };
164
165 static struct osd_device_data_s osd_axg = {
166         .cpu_id = __MESON_CPU_MAJOR_ID_AXG,
167         .osd_ver = OSD_SIMPLE,
168         .afbc_type = NO_AFBC,
169         .osd_count = 1,
170         .has_deband = 1,
171         .has_lut = 1,
172         .has_rdma = 0,
173         .has_dolby_vision = 0,
174          /* use iomap its self, no rdma, no canvas, no freescale */
175         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
176         .vpp_fifo_len = 0x400,
177         .dummy_data = 0x00808000,
178         .has_viu2 = 0,
179 };
180
181 static struct osd_device_data_s osd_g12a = {
182         .cpu_id = __MESON_CPU_MAJOR_ID_G12A,
183         .osd_ver = OSD_HIGH_ONE,
184         .afbc_type = MALI_AFBC,
185         .osd_count = 4,
186         .has_deband = 1,
187         .has_lut = 1,
188         .has_rdma = 1,
189         .has_dolby_vision = 0,
190         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
191         .vpp_fifo_len = 0xfff,/* 2048 */
192         .dummy_data = 0x00808000,
193         .has_viu2 = 1,
194 };
195
196 static struct osd_device_data_s osd_g12b = {
197         .cpu_id = __MESON_CPU_MAJOR_ID_G12B,
198         .osd_ver = OSD_HIGH_ONE,
199         .afbc_type = MALI_AFBC,
200         .osd_count = 4,
201         .has_deband = 1,
202         .has_lut = 1,
203         .has_rdma = 1,
204         .has_dolby_vision = 0,
205         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
206         .vpp_fifo_len = 0xfff,/* 2048 */
207         .dummy_data = 0x00808000,
208         .has_viu2 = 1,
209 };
210
211 static struct osd_device_data_s osd_tl1 = {
212         .cpu_id = __MESON_CPU_MAJOR_ID_TL1,
213         .osd_ver = OSD_HIGH_ONE,
214         .afbc_type = MALI_AFBC,
215         .osd_count = 3,
216         .has_deband = 1,
217         .has_lut = 1,
218         .has_rdma = 1,
219         .has_dolby_vision = 0,
220         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
221         .vpp_fifo_len = 0xfff,/* 2048 */
222         .dummy_data = 0x00808000,
223         .has_viu2 = 1,
224         .osd0_sc_independ = 0,
225 };
226
227 static struct osd_device_data_s osd_sm1 = {
228         .cpu_id = __MESON_CPU_MAJOR_ID_SM1,
229         .osd_ver = OSD_HIGH_ONE,
230         .afbc_type = MALI_AFBC,
231         .osd_count = 4,
232         .has_deband = 1,
233         .has_lut = 1,
234         .has_rdma = 1,
235         .has_dolby_vision = 1,
236         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
237         .vpp_fifo_len = 0xfff,/* 2048 */
238         .dummy_data = 0x00808000,
239         .has_viu2 = 1,
240         .osd0_sc_independ = 0,
241 };
242
243 static struct osd_device_data_s osd_tm2 = {
244         .cpu_id = __MESON_CPU_MAJOR_ID_TM2,
245         .osd_ver = OSD_HIGH_ONE,
246         .afbc_type = MALI_AFBC,
247         .osd_count = 4,
248         .has_deband = 1,
249         .has_lut = 1,
250         .has_rdma = 1,
251         .has_dolby_vision = 1,
252         .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
253         .vpp_fifo_len = 0xfff,/* 2048 */
254         .dummy_data = 0x00808000,
255         .has_viu2 = 1,
256         .osd0_sc_independ = 1,
257 };
258 struct osd_device_data_s osd_meson_dev;
259 static u32 logo_memsize;
260 static struct page *logo_page;
261 static struct delayed_work osd_dwork;
262 static struct platform_device *gp_dev;
263 static unsigned long gem_mem_start, gem_mem_size;
264
265 int am_meson_crtc_dts_info_set(const void *dt_match_data)
266 {
267         struct osd_device_data_s *osd_meson;
268
269         osd_meson = (struct osd_device_data_s *)dt_match_data;
270         if (osd_meson) {
271                 memcpy(&osd_meson_dev, osd_meson,
272                         sizeof(struct osd_device_data_s));
273                 osd_meson_dev.viu1_osd_count = osd_meson_dev.osd_count;
274                 if (osd_meson_dev.has_viu2) {
275                         /* set viu1 osd count */
276                         osd_meson_dev.viu1_osd_count--;
277                         osd_meson_dev.viu2_index = osd_meson_dev.viu1_osd_count;
278                 }
279         } else {
280                 DRM_ERROR("%s data NOT match\n", __func__);
281                 return -1;
282         }
283
284         return 0;
285 }
286
287 static int am_meson_crtc_loader_protect(struct drm_crtc *crtc, bool on)
288 {
289         struct am_meson_crtc *amcrtc = to_am_meson_crtc(crtc);
290
291         DRM_INFO("%s  %d\n", __func__, on);
292
293         if (on) {
294                 enable_irq(amcrtc->irq);
295                 drm_crtc_vblank_on(crtc);
296         } else {
297                 disable_irq(amcrtc->irq);
298                 drm_crtc_vblank_off(crtc);
299         }
300
301         return 0;
302 }
303
304 static int am_meson_crtc_enable_vblank(struct drm_crtc *crtc)
305 {
306         return 0;
307 }
308
309 static void am_meson_crtc_disable_vblank(struct drm_crtc *crtc)
310 {
311 }
312
313 const struct meson_crtc_funcs meson_private_crtc_funcs = {
314         .loader_protect = am_meson_crtc_loader_protect,
315         .enable_vblank = am_meson_crtc_enable_vblank,
316         .disable_vblank = am_meson_crtc_disable_vblank,
317 };
318
319 char *am_meson_crtc_get_voutmode(struct drm_display_mode *mode)
320 {
321         int i;
322         struct vinfo_s *vinfo;
323
324         vinfo = get_current_vinfo();
325
326         if (vinfo && vinfo->mode == VMODE_LCD)
327                 return mode->name;
328
329         for (i = 0; i < ARRAY_SIZE(am_vout_modes); i++) {
330                 if (am_vout_modes[i].width == mode->hdisplay &&
331                     am_vout_modes[i].height == mode->vdisplay &&
332                     am_vout_modes[i].vrefresh == mode->vrefresh &&
333                     am_vout_modes[i].flags ==
334                     (mode->flags & DRM_MODE_FLAG_INTERLACE))
335                         return am_vout_modes[i].name;
336         }
337         return NULL;
338 }
339
340 void am_meson_crtc_handle_vsync(struct am_meson_crtc *amcrtc)
341 {
342         unsigned long flags;
343         struct drm_crtc *crtc;
344
345         crtc = &amcrtc->base;
346         drm_crtc_handle_vblank(crtc);
347
348         spin_lock_irqsave(&crtc->dev->event_lock, flags);
349         if (amcrtc->event) {
350                 drm_crtc_send_vblank_event(crtc, amcrtc->event);
351                 drm_crtc_vblank_put(crtc);
352                 amcrtc->event = NULL;
353         }
354         spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
355 }
356
357 void am_meson_crtc_irq(struct meson_drm *priv)
358 {
359         struct am_meson_crtc *amcrtc = to_am_meson_crtc(priv->crtc);
360
361         am_meson_crtc_handle_vsync(amcrtc);
362 }
363
364 static irqreturn_t am_meson_vpu_irq(int irq, void *arg)
365 {
366         struct drm_device *dev = arg;
367         struct meson_drm *priv = dev->dev_private;
368
369         am_meson_crtc_irq(priv);
370
371         return IRQ_HANDLED;
372 }
373
374 static void mem_free_work(struct work_struct *work)
375 {
376         if (logo_memsize > 0) {
377 #ifdef CONFIG_CMA
378                 pr_info("%s, free memory: addr:0x%x\n",
379                         __func__, logo_memsize);
380
381                 dma_release_from_contiguous(&gp_dev->dev,
382                                             logo_page,
383                         logo_memsize >> PAGE_SHIFT);
384 #endif
385         }
386 }
387
388 static int am_meson_vpu_bind(struct device *dev,
389                                 struct device *master, void *data)
390 {
391         struct platform_device *pdev = to_platform_device(dev);
392         struct drm_device *drm_dev = data;
393         struct meson_drm *private = drm_dev->dev_private;
394         struct meson_vpu_pipeline *pipeline = private->pipeline;
395         struct am_meson_crtc *amcrtc;
396 #ifdef CONFIG_CMA
397         struct cma *cma;
398 #endif
399         int ret, irq;
400
401         /* Allocate crtc struct */
402         pr_info("[%s] in\n", __func__);
403         amcrtc = devm_kzalloc(dev, sizeof(*amcrtc),
404                               GFP_KERNEL);
405         if (!amcrtc)
406                 return -ENOMEM;
407
408         amcrtc->priv = private;
409         amcrtc->dev = dev;
410         amcrtc->drm_dev = drm_dev;
411
412         dev_set_drvdata(dev, amcrtc);
413
414         /* init reserved memory */
415         ret = of_reserved_mem_device_init(&pdev->dev);
416         if (ret != 0) {
417                 dev_err(dev, "failed to init reserved memory\n");
418 #ifdef CONFIG_CMA
419                 gp_dev = pdev;
420                 cma = dev_get_cma_area(&pdev->dev);
421                 if (cma) {
422                         logo_memsize = cma_get_size(cma);
423                         pr_info("reserved memory base:0x%x, size:0x%x\n",
424                                 (u32)cma_get_base(cma), logo_memsize);
425                         if (logo_memsize > 0) {
426                                 logo_page =
427                                 dma_alloc_from_contiguous(&pdev->dev,
428                                                           logo_memsize >>
429                                                           PAGE_SHIFT,
430                                                           0);
431                                 if (!logo_page) {
432                                         pr_err("allocate buffer failed:%d\n",
433                                                logo_memsize);
434                                 }
435                         }
436                 } else {
437                         pr_info("------ NO CMA\n");
438                 }
439 #endif
440         } else {
441                 dma_declare_coherent_memory(drm_dev->dev, gem_mem_start,
442                                             gem_mem_start, gem_mem_size,
443                                             DMA_MEMORY_EXCLUSIVE);
444                 pr_info("meson drm mem_start = 0x%x, size = 0x%x\n",
445                         (u32)gem_mem_start, (u32)gem_mem_size);
446         }
447
448         ret = am_meson_plane_create(private);
449         if (ret)
450                 return ret;
451
452         ret = am_meson_crtc_create(amcrtc);
453         if (ret)
454                 return ret;
455
456         am_meson_register_crtc_funcs(private->crtc, &meson_private_crtc_funcs);
457
458         ret = of_property_read_u8(dev->of_node,
459                                   "osd_ver", &pipeline->osd_version);
460         vpu_pipeline_init(pipeline);
461
462         /*vsync irq.*/
463         irq = platform_get_irq(pdev, 0);
464         if (irq < 0) {
465                 dev_err(dev, "cannot find irq for vpu\n");
466                 return irq;
467         }
468         amcrtc->irq = (unsigned int)irq;
469
470         ret = devm_request_irq(dev, amcrtc->irq, am_meson_vpu_irq,
471                 IRQF_SHARED, dev_name(dev), drm_dev);
472         if (ret)
473                 return ret;
474
475         /* IRQ is initially disabled; it gets enabled in crtc_enable */
476         disable_irq(amcrtc->irq);
477
478         INIT_DELAYED_WORK(&osd_dwork, mem_free_work);
479         schedule_delayed_work(&osd_dwork, msecs_to_jiffies(60 * 1000));
480         pr_info("[%s] out\n", __func__);
481         return 0;
482 }
483
484 static void am_meson_vpu_unbind(struct device *dev,
485                                 struct device *master, void *data)
486 {
487         struct drm_device *drm_dev = data;
488         struct meson_drm *private = drm_dev->dev_private;
489
490         am_meson_unregister_crtc_funcs(private->crtc);
491 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT
492         amvecm_drm_gamma_disable(0);
493         am_meson_ctm_disable();
494 #endif
495         osd_drm_debugfs_exit();
496 }
497
498 static const struct component_ops am_meson_vpu_component_ops = {
499         .bind = am_meson_vpu_bind,
500         .unbind = am_meson_vpu_unbind,
501 };
502
503 static const struct of_device_id am_meson_vpu_driver_dt_match[] = {
504         { .compatible = "amlogic,meson-gxbb-vpu",
505          .data = &osd_gxbb, },
506         { .compatible = "amlogic,meson-gxl-vpu",
507          .data = &osd_gxl, },
508         { .compatible = "amlogic,meson-gxm-vpu",
509          .data = &osd_gxm, },
510         { .compatible = "amlogic,meson-txl-vpu",
511          .data = &osd_txl, },
512         { .compatible = "amlogic,meson-txlx-vpu",
513          .data = &osd_txlx, },
514         { .compatible = "amlogic,meson-axg-vpu",
515          .data = &osd_axg, },
516         { .compatible = "amlogic,meson-g12a-vpu",
517          .data = &osd_g12a, },
518         { .compatible = "amlogic,meson-g12b-vpu",
519         .data = &osd_g12b, },
520         {.compatible = "amlogic, meson-tl1-vpu",
521         .data = &osd_tl1,},
522         {.compatible = "amlogic, meson-sm1-vpu",
523         .data = &osd_sm1,},
524         {.compatible = "amlogic, meson-tm2-vpu",
525         .data = &osd_tm2,},
526         {}
527 };
528
529 MODULE_DEVICE_TABLE(of, am_meson_vpu_driver_dt_match);
530
531 static int am_meson_vpu_probe(struct platform_device *pdev)
532 {
533         struct device *dev = &pdev->dev;
534         const void *vpu_data;
535         int ret;
536
537         pr_info("[%s] in\n", __func__);
538         if (!dev->of_node) {
539                 dev_err(dev, "can't find vpu devices\n");
540                 return -ENODEV;
541         }
542
543         vpu_data = of_device_get_match_data(dev);
544         if (vpu_data) {
545                 ret = am_meson_crtc_dts_info_set(vpu_data);
546                 if (ret < 0)
547                         return -ENODEV;
548         } else {
549                 dev_err(dev, "%s NOT match\n", __func__);
550                 return -ENODEV;
551         }
552         pr_info("[%s] out\n", __func__);
553         return component_add(dev, &am_meson_vpu_component_ops);
554 }
555
556 static int am_meson_vpu_remove(struct platform_device *pdev)
557 {
558         component_del(&pdev->dev, &am_meson_vpu_component_ops);
559
560         return 0;
561 }
562
563 static struct platform_driver am_meson_vpu_platform_driver = {
564         .probe = am_meson_vpu_probe,
565         .remove = am_meson_vpu_remove,
566         .driver = {
567                 .name = "meson-vpu",
568                 .owner = THIS_MODULE,
569                 .of_match_table = of_match_ptr(am_meson_vpu_driver_dt_match),
570         },
571 };
572
573 static int gem_mem_device_init(struct reserved_mem *rmem, struct device *dev)
574 {
575         s32 ret = 0;
576
577         if (!rmem) {
578                 pr_info("Can't get reverse mem!\n");
579                 ret = -EFAULT;
580                 return ret;
581         }
582         gem_mem_start = rmem->base;
583         gem_mem_size = rmem->size;
584         pr_info("init gem memsource addr:0x%x size:0x%x\n",
585                 (u32)gem_mem_start, (u32)gem_mem_size);
586
587         return 0;
588 }
589
590 static const struct reserved_mem_ops rmem_gem_ops = {
591         .device_init = gem_mem_device_init,
592 };
593
594 static int __init gem_mem_setup(struct reserved_mem *rmem)
595 {
596         rmem->ops = &rmem_gem_ops;
597         pr_info("gem mem setup\n");
598         return 0;
599 }
600
601 RESERVEDMEM_OF_DECLARE(gem, "amlogic, gem_memory", gem_mem_setup);
602
603 module_platform_driver(am_meson_vpu_platform_driver);
604
605 MODULE_AUTHOR("MultiMedia Amlogic <multimedia-sh@amlogic.com>");
606 MODULE_DESCRIPTION("Amlogic Meson Drm VPU driver");
607 MODULE_LICENSE("GPL");