aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-08-20 00:11:17 -0400
committerDave Airlie <airlied@redhat.com>2015-08-20 00:11:17 -0400
commitaaba64487a96df6584a05d8898634307f3c86790 (patch)
treea6a9690ee1491b7ffd3f8456c9c1575021f8d1a0 /drivers
parentd072f4654464b242e536a03102ebd3d481f6b418 (diff)
parentb55a1b9c55ee9ed5b7d1d2acbabb078a454dbeea (diff)
Merge branch 'drm-next-fsl-dcu' of https://github.com/Jianwei-Wang/linux-drm-fsl-dcu into drm-next
Merge Freescale DCU FRM driver. * 'drm-next-fsl-dcu' of https://github.com/Jianwei-Wang/linux-drm-fsl-dcu: MAINTAINERS: Add Freescale DCU DRM driver maintainer devicetree: Add NEC to the vendor-prefix list drm/layerscape: Add Freescale DCU DRM driver
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/fsl-dcu/Kconfig18
-rw-r--r--drivers/gpu/drm/fsl-dcu/Makefile7
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c210
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.h19
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c404
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h197
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c23
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c43
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h33
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c261
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h17
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c182
14 files changed, 1417 insertions, 0 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index df99b0132134..1a0a8df2eed8 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -251,6 +251,8 @@ source "drivers/gpu/drm/virtio/Kconfig"
251 251
252source "drivers/gpu/drm/msm/Kconfig" 252source "drivers/gpu/drm/msm/Kconfig"
253 253
254source "drivers/gpu/drm/fsl-dcu/Kconfig"
255
254source "drivers/gpu/drm/tegra/Kconfig" 256source "drivers/gpu/drm/tegra/Kconfig"
255 257
256source "drivers/gpu/drm/panel/Kconfig" 258source "drivers/gpu/drm/panel/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 8858510437ea..45e7719846b1 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_DRM_IMX) += imx/
70obj-y += i2c/ 70obj-y += i2c/
71obj-y += panel/ 71obj-y += panel/
72obj-y += bridge/ 72obj-y += bridge/
73obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig
new file mode 100644
index 000000000000..c78cf3f605d0
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/Kconfig
@@ -0,0 +1,18 @@
1config DRM_FSL_DCU
2 tristate "DRM Support for Freescale DCU"
3 depends on DRM && OF && ARM
4 select BACKLIGHT_CLASS_DEVICE
5 select BACKLIGHT_LCD_SUPPORT
6 select DRM_KMS_HELPER
7 select DRM_KMS_CMA_HELPER
8 select DRM_KMS_FB_HELPER
9 select DRM_PANEL
10 select FB_SYS_FILLRECT
11 select FB_SYS_COPYAREA
12 select FB_SYS_IMAGEBLIT
13 select FB_SYS_FOPS
14 select REGMAP_MMIO
15 select VIDEOMODE_HELPERS
16 help
17 Choose this option if you have an Freescale DCU chipset.
18 If M is selected the module will be called fsl-dcu-drm.
diff --git a/drivers/gpu/drm/fsl-dcu/Makefile b/drivers/gpu/drm/fsl-dcu/Makefile
new file mode 100644
index 000000000000..6ea1523ae6ec
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/Makefile
@@ -0,0 +1,7 @@
1fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
2 fsl_dcu_drm_kms.o \
3 fsl_dcu_drm_rgb.o \
4 fsl_dcu_drm_plane.o \
5 fsl_dcu_drm_crtc.o \
6 fsl_dcu_drm_fbdev.o
7obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu-drm.o
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
new file mode 100644
index 000000000000..82a3d311e164
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
@@ -0,0 +1,210 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#include <linux/clk.h>
13#include <linux/regmap.h>
14
15#include <drm/drmP.h>
16#include <drm/drm_atomic.h>
17#include <drm/drm_atomic_helper.h>
18#include <drm/drm_crtc.h>
19#include <drm/drm_crtc_helper.h>
20
21#include "fsl_dcu_drm_crtc.h"
22#include "fsl_dcu_drm_drv.h"
23#include "fsl_dcu_drm_plane.h"
24
25static void fsl_dcu_drm_crtc_atomic_begin(struct drm_crtc *crtc,
26 struct drm_crtc_state *old_crtc_state)
27{
28}
29
30static int fsl_dcu_drm_crtc_atomic_check(struct drm_crtc *crtc,
31 struct drm_crtc_state *state)
32{
33 return 0;
34}
35
36static void fsl_dcu_drm_crtc_atomic_flush(struct drm_crtc *crtc,
37 struct drm_crtc_state *old_crtc_state)
38{
39}
40
41static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)
42{
43 struct drm_device *dev = crtc->dev;
44 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
45 int ret;
46
47 ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
48 DCU_MODE_DCU_MODE_MASK,
49 DCU_MODE_DCU_MODE(DCU_MODE_OFF));
50 if (ret)
51 dev_err(fsl_dev->dev, "Disable CRTC failed\n");
52 ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
53 DCU_UPDATE_MODE_READREG);
54 if (ret)
55 dev_err(fsl_dev->dev, "Enable CRTC failed\n");
56}
57
58static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
59{
60 struct drm_device *dev = crtc->dev;
61 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
62 int ret;
63
64 ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
65 DCU_MODE_DCU_MODE_MASK,
66 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
67 if (ret)
68 dev_err(fsl_dev->dev, "Enable CRTC failed\n");
69 ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
70 DCU_UPDATE_MODE_READREG);
71 if (ret)
72 dev_err(fsl_dev->dev, "Enable CRTC failed\n");
73}
74
75static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
76 const struct drm_display_mode *mode,
77 struct drm_display_mode *adjusted_mode)
78{
79 return true;
80}
81
82static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
83{
84 struct drm_device *dev = crtc->dev;
85 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
86 struct drm_display_mode *mode = &crtc->state->mode;
87 unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index;
88 unsigned long dcuclk;
89 int ret;
90
91 index = drm_crtc_index(crtc);
92 dcuclk = clk_get_rate(fsl_dev->clk);
93 div = dcuclk / mode->clock / 1000;
94
95 /* Configure timings: */
96 hbp = mode->htotal - mode->hsync_end;
97 hfp = mode->hsync_start - mode->hdisplay;
98 hsw = mode->hsync_end - mode->hsync_start;
99 vbp = mode->vtotal - mode->vsync_end;
100 vfp = mode->vsync_start - mode->vdisplay;
101 vsw = mode->vsync_end - mode->vsync_start;
102
103 ret = regmap_write(fsl_dev->regmap, DCU_HSYN_PARA,
104 DCU_HSYN_PARA_BP(hbp) |
105 DCU_HSYN_PARA_PW(hsw) |
106 DCU_HSYN_PARA_FP(hfp));
107 if (ret)
108 goto set_failed;
109 ret = regmap_write(fsl_dev->regmap, DCU_VSYN_PARA,
110 DCU_VSYN_PARA_BP(vbp) |
111 DCU_VSYN_PARA_PW(vsw) |
112 DCU_VSYN_PARA_FP(vfp));
113 if (ret)
114 goto set_failed;
115 ret = regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
116 DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
117 DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
118 if (ret)
119 goto set_failed;
120 ret = regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
121 if (ret)
122 goto set_failed;
123 ret = regmap_write(fsl_dev->regmap, DCU_SYN_POL,
124 DCU_SYN_POL_INV_VS_LOW | DCU_SYN_POL_INV_HS_LOW);
125 if (ret)
126 goto set_failed;
127 ret = regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
128 DCU_BGND_G(0) | DCU_BGND_B(0));
129 if (ret)
130 goto set_failed;
131 ret = regmap_write(fsl_dev->regmap, DCU_DCU_MODE,
132 DCU_MODE_BLEND_ITER(1) | DCU_MODE_RASTER_EN);
133 if (ret)
134 goto set_failed;
135 ret = regmap_write(fsl_dev->regmap, DCU_THRESHOLD,
136 DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |
137 DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |
138 DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL));
139 if (ret)
140 goto set_failed;
141 ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
142 DCU_UPDATE_MODE_READREG);
143 if (ret)
144 goto set_failed;
145 return;
146set_failed:
147 dev_err(dev->dev, "set DCU register failed\n");
148}
149
150static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
151 .atomic_begin = fsl_dcu_drm_crtc_atomic_begin,
152 .atomic_check = fsl_dcu_drm_crtc_atomic_check,
153 .atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
154 .disable = fsl_dcu_drm_disable_crtc,
155 .enable = fsl_dcu_drm_crtc_enable,
156 .mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
157 .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
158};
159
160static const struct drm_crtc_funcs fsl_dcu_drm_crtc_funcs = {
161 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
162 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
163 .destroy = drm_crtc_cleanup,
164 .page_flip = drm_atomic_helper_page_flip,
165 .reset = drm_atomic_helper_crtc_reset,
166 .set_config = drm_atomic_helper_set_config,
167};
168
169int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev)
170{
171 struct drm_plane *primary;
172 struct drm_crtc *crtc = &fsl_dev->crtc;
173 unsigned int i, j, reg_num;
174 int ret;
175
176 primary = fsl_dcu_drm_primary_create_plane(fsl_dev->drm);
177 ret = drm_crtc_init_with_planes(fsl_dev->drm, crtc, primary, NULL,
178 &fsl_dcu_drm_crtc_funcs);
179 if (ret < 0)
180 return ret;
181
182 drm_crtc_helper_add(crtc, &fsl_dcu_drm_crtc_helper_funcs);
183
184 if (!strcmp(fsl_dev->soc->name, "ls1021a"))
185 reg_num = LS1021A_LAYER_REG_NUM;
186 else
187 reg_num = VF610_LAYER_REG_NUM;
188 for (i = 0; i <= fsl_dev->soc->total_layer; i++) {
189 for (j = 0; j < reg_num; j++) {
190 ret = regmap_write(fsl_dev->regmap,
191 DCU_CTRLDESCLN(i, j), 0);
192 if (ret)
193 goto init_failed;
194 }
195 }
196 ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
197 DCU_MODE_DCU_MODE_MASK,
198 DCU_MODE_DCU_MODE(DCU_MODE_OFF));
199 if (ret)
200 goto init_failed;
201 ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
202 DCU_UPDATE_MODE_READREG);
203 if (ret)
204 goto init_failed;
205
206 return 0;
207init_failed:
208 dev_err(fsl_dev->dev, "init DCU register failed\n");
209 return ret;
210}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.h
new file mode 100644
index 000000000000..43d4da2c5fe5
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.h
@@ -0,0 +1,19 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#ifndef __FSL_DCU_DRM_CRTC_H__
13#define __FSL_DCU_DRM_CRTC_H__
14
15struct fsl_dcu_drm_device;
16
17int fsl_dcu_drm_crtc_create(struct fsl_dcu_drm_device *fsl_dev);
18
19#endif /* __FSL_DCU_DRM_CRTC_H__ */
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
new file mode 100644
index 000000000000..9a8e2da47158
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -0,0 +1,404 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#include <linux/clk.h>
13#include <linux/clk-provider.h>
14#include <linux/io.h>
15#include <linux/mfd/syscon.h>
16#include <linux/mm.h>
17#include <linux/module.h>
18#include <linux/of_platform.h>
19#include <linux/platform_device.h>
20#include <linux/pm.h>
21#include <linux/pm_runtime.h>
22#include <linux/regmap.h>
23
24#include <drm/drmP.h>
25#include <drm/drm_crtc_helper.h>
26#include <drm/drm_gem_cma_helper.h>
27
28#include "fsl_dcu_drm_crtc.h"
29#include "fsl_dcu_drm_drv.h"
30
31static const struct regmap_config fsl_dcu_regmap_config = {
32 .reg_bits = 32,
33 .reg_stride = 4,
34 .val_bits = 32,
35 .cache_type = REGCACHE_RBTREE,
36};
37
38static int fsl_dcu_drm_irq_init(struct drm_device *dev)
39{
40 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
41 unsigned int value;
42 int ret;
43
44 ret = drm_irq_install(dev, fsl_dev->irq);
45 if (ret < 0)
46 dev_err(dev->dev, "failed to install IRQ handler\n");
47
48 ret = regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0);
49 if (ret)
50 dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
51 ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
52 if (ret)
53 dev_err(dev->dev, "read DCU_INT_MASK failed\n");
54 value &= DCU_INT_MASK_VBLANK;
55 ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
56 if (ret)
57 dev_err(dev->dev, "set DCU_INT_MASK failed\n");
58 ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
59 DCU_UPDATE_MODE_READREG);
60 if (ret)
61 dev_err(dev->dev, "set DCU_UPDATE_MODE failed\n");
62
63 return ret;
64}
65
66static int fsl_dcu_load(struct drm_device *drm, unsigned long flags)
67{
68 struct device *dev = drm->dev;
69 struct fsl_dcu_drm_device *fsl_dev = drm->dev_private;
70 int ret;
71
72 ret = fsl_dcu_drm_modeset_init(fsl_dev);
73 if (ret < 0) {
74 dev_err(dev, "failed to initialize mode setting\n");
75 return ret;
76 }
77
78 ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
79 if (ret < 0) {
80 dev_err(dev, "failed to initialize vblank\n");
81 goto done;
82 }
83 drm->vblank_disable_allowed = true;
84
85 ret = fsl_dcu_drm_irq_init(drm);
86 if (ret < 0)
87 goto done;
88 drm->irq_enabled = true;
89
90 fsl_dcu_fbdev_init(drm);
91
92 return 0;
93done:
94 if (ret) {
95 drm_mode_config_cleanup(drm);
96 drm_vblank_cleanup(drm);
97 drm_irq_uninstall(drm);
98 drm->dev_private = NULL;
99 }
100
101 return ret;
102}
103
104static int fsl_dcu_unload(struct drm_device *dev)
105{
106 drm_mode_config_cleanup(dev);
107 drm_vblank_cleanup(dev);
108 drm_irq_uninstall(dev);
109
110 dev->dev_private = NULL;
111
112 return 0;
113}
114
115static void fsl_dcu_drm_preclose(struct drm_device *dev, struct drm_file *file)
116{
117}
118
119static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg)
120{
121 struct drm_device *dev = arg;
122 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
123 unsigned int int_status;
124 int ret;
125
126 ret = regmap_read(fsl_dev->regmap, DCU_INT_STATUS, &int_status);
127 if (ret)
128 dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
129 if (int_status & DCU_INT_STATUS_VBLANK)
130 drm_handle_vblank(dev, 0);
131
132 ret = regmap_write(fsl_dev->regmap, DCU_INT_STATUS, 0xffffffff);
133 if (ret)
134 dev_err(dev->dev, "set DCU_INT_STATUS failed\n");
135 ret = regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,
136 DCU_UPDATE_MODE_READREG);
137 if (ret)
138 dev_err(dev->dev, "set DCU_UPDATE_MODE failed\n");
139
140 return IRQ_HANDLED;
141}
142
143static int fsl_dcu_drm_enable_vblank(struct drm_device *dev, int crtc)
144{
145 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
146 unsigned int value;
147 int ret;
148
149 ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
150 if (ret)
151 dev_err(dev->dev, "read DCU_INT_MASK failed\n");
152 value &= ~DCU_INT_MASK_VBLANK;
153 ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
154 if (ret)
155 dev_err(dev->dev, "set DCU_INT_MASK failed\n");
156 return 0;
157}
158
159static void fsl_dcu_drm_disable_vblank(struct drm_device *dev, int crtc)
160{
161 struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
162 unsigned int value;
163 int ret;
164
165 ret = regmap_read(fsl_dev->regmap, DCU_INT_MASK, &value);
166 if (ret)
167 dev_err(dev->dev, "read DCU_INT_MASK failed\n");
168 value |= DCU_INT_MASK_VBLANK;
169 ret = regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
170 if (ret)
171 dev_err(dev->dev, "set DCU_INT_MASK failed\n");
172}
173
174static const struct file_operations fsl_dcu_drm_fops = {
175 .owner = THIS_MODULE,
176 .open = drm_open,
177 .release = drm_release,
178 .unlocked_ioctl = drm_ioctl,
179#ifdef CONFIG_COMPAT
180 .compat_ioctl = drm_compat_ioctl,
181#endif
182 .poll = drm_poll,
183 .read = drm_read,
184 .llseek = no_llseek,
185 .mmap = drm_gem_cma_mmap,
186};
187
188static struct drm_driver fsl_dcu_drm_driver = {
189 .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
190 | DRIVER_PRIME | DRIVER_ATOMIC,
191 .load = fsl_dcu_load,
192 .unload = fsl_dcu_unload,
193 .preclose = fsl_dcu_drm_preclose,
194 .irq_handler = fsl_dcu_drm_irq,
195 .get_vblank_counter = drm_vblank_count,
196 .enable_vblank = fsl_dcu_drm_enable_vblank,
197 .disable_vblank = fsl_dcu_drm_disable_vblank,
198 .gem_free_object = drm_gem_cma_free_object,
199 .gem_vm_ops = &drm_gem_cma_vm_ops,
200 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
201 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
202 .gem_prime_import = drm_gem_prime_import,
203 .gem_prime_export = drm_gem_prime_export,
204 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
205 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
206 .gem_prime_vmap = drm_gem_cma_prime_vmap,
207 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
208 .gem_prime_mmap = drm_gem_cma_prime_mmap,
209 .dumb_create = drm_gem_cma_dumb_create,
210 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
211 .dumb_destroy = drm_gem_dumb_destroy,
212 .fops = &fsl_dcu_drm_fops,
213 .name = "fsl-dcu-drm",
214 .desc = "Freescale DCU DRM",
215 .date = "20150213",
216 .major = 1,
217 .minor = 0,
218};
219
220#ifdef CONFIG_PM_SLEEP
221static int fsl_dcu_drm_pm_suspend(struct device *dev)
222{
223 struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
224
225 if (!fsl_dev)
226 return 0;
227
228 drm_kms_helper_poll_disable(fsl_dev->drm);
229 regcache_cache_only(fsl_dev->regmap, true);
230 regcache_mark_dirty(fsl_dev->regmap);
231 clk_disable(fsl_dev->clk);
232 clk_unprepare(fsl_dev->clk);
233
234 return 0;
235}
236
237static int fsl_dcu_drm_pm_resume(struct device *dev)
238{
239 struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev);
240 int ret;
241
242 if (!fsl_dev)
243 return 0;
244
245 ret = clk_enable(fsl_dev->clk);
246 if (ret < 0) {
247 dev_err(dev, "failed to enable dcu clk\n");
248 clk_unprepare(fsl_dev->clk);
249 return ret;
250 }
251 ret = clk_prepare(fsl_dev->clk);
252 if (ret < 0) {
253 dev_err(dev, "failed to prepare dcu clk\n");
254 return ret;
255 }
256
257 drm_kms_helper_poll_enable(fsl_dev->drm);
258 regcache_cache_only(fsl_dev->regmap, false);
259 regcache_sync(fsl_dev->regmap);
260
261 return 0;
262}
263#endif
264
265static const struct dev_pm_ops fsl_dcu_drm_pm_ops = {
266 SET_SYSTEM_SLEEP_PM_OPS(fsl_dcu_drm_pm_suspend, fsl_dcu_drm_pm_resume)
267};
268
269static const struct fsl_dcu_soc_data fsl_dcu_ls1021a_data = {
270 .name = "ls1021a",
271 .total_layer = 16,
272 .max_layer = 4,
273};
274
275static const struct fsl_dcu_soc_data fsl_dcu_vf610_data = {
276 .name = "vf610",
277 .total_layer = 64,
278 .max_layer = 6,
279};
280
281static const struct of_device_id fsl_dcu_of_match[] = {
282 {
283 .compatible = "fsl,ls1021a-dcu",
284 .data = &fsl_dcu_ls1021a_data,
285 }, {
286 .compatible = "fsl,vf610-dcu",
287 .data = &fsl_dcu_vf610_data,
288 }, {
289 },
290};
291MODULE_DEVICE_TABLE(of, fsl_dcu_of_match);
292
293static int fsl_dcu_drm_probe(struct platform_device *pdev)
294{
295 struct fsl_dcu_drm_device *fsl_dev;
296 struct drm_device *drm;
297 struct device *dev = &pdev->dev;
298 struct resource *res;
299 void __iomem *base;
300 struct drm_driver *driver = &fsl_dcu_drm_driver;
301 const struct of_device_id *id;
302 int ret;
303
304 fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL);
305 if (!fsl_dev)
306 return -ENOMEM;
307
308 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
309 if (!res) {
310 dev_err(dev, "could not get memory IO resource\n");
311 return -ENODEV;
312 }
313
314 base = devm_ioremap_resource(dev, res);
315 if (IS_ERR(base)) {
316 ret = PTR_ERR(base);
317 return ret;
318 }
319
320 fsl_dev->irq = platform_get_irq(pdev, 0);
321 if (fsl_dev->irq < 0) {
322 dev_err(dev, "failed to get irq\n");
323 return -ENXIO;
324 }
325
326 fsl_dev->clk = devm_clk_get(dev, "dcu");
327 if (IS_ERR(fsl_dev->clk)) {
328 ret = PTR_ERR(fsl_dev->clk);
329 dev_err(dev, "failed to get dcu clock\n");
330 return ret;
331 }
332 ret = clk_prepare(fsl_dev->clk);
333 if (ret < 0) {
334 dev_err(dev, "failed to prepare dcu clk\n");
335 return ret;
336 }
337 ret = clk_enable(fsl_dev->clk);
338 if (ret < 0) {
339 dev_err(dev, "failed to enable dcu clk\n");
340 clk_unprepare(fsl_dev->clk);
341 return ret;
342 }
343
344 fsl_dev->regmap = devm_regmap_init_mmio(dev, base,
345 &fsl_dcu_regmap_config);
346 if (IS_ERR(fsl_dev->regmap)) {
347 dev_err(dev, "regmap init failed\n");
348 return PTR_ERR(fsl_dev->regmap);
349 }
350
351 id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node);
352 if (!id)
353 return -ENODEV;
354 fsl_dev->soc = id->data;
355
356 drm = drm_dev_alloc(driver, dev);
357 if (!drm)
358 return -ENOMEM;
359
360 fsl_dev->dev = dev;
361 fsl_dev->drm = drm;
362 fsl_dev->np = dev->of_node;
363 drm->dev_private = fsl_dev;
364 dev_set_drvdata(dev, fsl_dev);
365 drm_dev_set_unique(drm, dev_name(dev));
366
367 ret = drm_dev_register(drm, 0);
368 if (ret < 0)
369 goto unref;
370
371 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name,
372 driver->major, driver->minor, driver->patchlevel,
373 driver->date, drm->primary->index);
374
375 return 0;
376
377unref:
378 drm_dev_unref(drm);
379 return ret;
380}
381
382static int fsl_dcu_drm_remove(struct platform_device *pdev)
383{
384 struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
385
386 drm_put_dev(fsl_dev->drm);
387
388 return 0;
389}
390
391static struct platform_driver fsl_dcu_drm_platform_driver = {
392 .probe = fsl_dcu_drm_probe,
393 .remove = fsl_dcu_drm_remove,
394 .driver = {
395 .name = "fsl-dcu",
396 .pm = &fsl_dcu_drm_pm_ops,
397 .of_match_table = fsl_dcu_of_match,
398 },
399};
400
401module_platform_driver(fsl_dcu_drm_platform_driver);
402
403MODULE_DESCRIPTION("Freescale DCU DRM Driver");
404MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
new file mode 100644
index 000000000000..579b9e44e764
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
@@ -0,0 +1,197 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#ifndef __FSL_DCU_DRM_DRV_H__
13#define __FSL_DCU_DRM_DRV_H__
14
15#include "fsl_dcu_drm_crtc.h"
16#include "fsl_dcu_drm_output.h"
17#include "fsl_dcu_drm_plane.h"
18
19#define DCU_DCU_MODE 0x0010
20#define DCU_MODE_BLEND_ITER(x) ((x) << 20)
21#define DCU_MODE_RASTER_EN BIT(14)
22#define DCU_MODE_DCU_MODE(x) (x)
23#define DCU_MODE_DCU_MODE_MASK 0x03
24#define DCU_MODE_OFF 0
25#define DCU_MODE_NORMAL 1
26#define DCU_MODE_TEST 2
27#define DCU_MODE_COLORBAR 3
28
29#define DCU_BGND 0x0014
30#define DCU_BGND_R(x) ((x) << 16)
31#define DCU_BGND_G(x) ((x) << 8)
32#define DCU_BGND_B(x) (x)
33
34#define DCU_DISP_SIZE 0x0018
35#define DCU_DISP_SIZE_DELTA_Y(x) ((x) << 16)
36/*Regisiter value 1/16 of horizontal resolution*/
37#define DCU_DISP_SIZE_DELTA_X(x) ((x) >> 4)
38
39#define DCU_HSYN_PARA 0x001c
40#define DCU_HSYN_PARA_BP(x) ((x) << 22)
41#define DCU_HSYN_PARA_PW(x) ((x) << 11)
42#define DCU_HSYN_PARA_FP(x) (x)
43
44#define DCU_VSYN_PARA 0x0020
45#define DCU_VSYN_PARA_BP(x) ((x) << 22)
46#define DCU_VSYN_PARA_PW(x) ((x) << 11)
47#define DCU_VSYN_PARA_FP(x) (x)
48
49#define DCU_SYN_POL 0x0024
50#define DCU_SYN_POL_INV_PXCK_FALL (0 << 6)
51#define DCU_SYN_POL_NEG_REMAIN (0 << 5)
52#define DCU_SYN_POL_INV_VS_LOW BIT(1)
53#define DCU_SYN_POL_INV_HS_LOW BIT(0)
54
55#define DCU_THRESHOLD 0x0028
56#define DCU_THRESHOLD_LS_BF_VS(x) ((x) << 16)
57#define DCU_THRESHOLD_OUT_BUF_HIGH(x) ((x) << 8)
58#define DCU_THRESHOLD_OUT_BUF_LOW(x) (x)
59#define BF_VS_VAL 0x03
60#define BUF_MAX_VAL 0x78
61#define BUF_MIN_VAL 0x0a
62
63#define DCU_INT_STATUS 0x002C
64#define DCU_INT_STATUS_VSYNC BIT(0)
65#define DCU_INT_STATUS_UNDRUN BIT(1)
66#define DCU_INT_STATUS_LSBFVS BIT(2)
67#define DCU_INT_STATUS_VBLANK BIT(3)
68#define DCU_INT_STATUS_CRCREADY BIT(4)
69#define DCU_INT_STATUS_CRCOVERFLOW BIT(5)
70#define DCU_INT_STATUS_P1FIFOLO BIT(6)
71#define DCU_INT_STATUS_P1FIFOHI BIT(7)
72#define DCU_INT_STATUS_P2FIFOLO BIT(8)
73#define DCU_INT_STATUS_P2FIFOHI BIT(9)
74#define DCU_INT_STATUS_PROGEND BIT(10)
75#define DCU_INT_STATUS_IPMERROR BIT(11)
76#define DCU_INT_STATUS_LYRTRANS BIT(12)
77#define DCU_INT_STATUS_DMATRANS BIT(14)
78#define DCU_INT_STATUS_P3FIFOLO BIT(16)
79#define DCU_INT_STATUS_P3FIFOHI BIT(17)
80#define DCU_INT_STATUS_P4FIFOLO BIT(18)
81#define DCU_INT_STATUS_P4FIFOHI BIT(19)
82#define DCU_INT_STATUS_P1EMPTY BIT(26)
83#define DCU_INT_STATUS_P2EMPTY BIT(27)
84#define DCU_INT_STATUS_P3EMPTY BIT(28)
85#define DCU_INT_STATUS_P4EMPTY BIT(29)
86
87#define DCU_INT_MASK 0x0030
88#define DCU_INT_MASK_VSYNC BIT(0)
89#define DCU_INT_MASK_UNDRUN BIT(1)
90#define DCU_INT_MASK_LSBFVS BIT(2)
91#define DCU_INT_MASK_VBLANK BIT(3)
92#define DCU_INT_MASK_CRCREADY BIT(4)
93#define DCU_INT_MASK_CRCOVERFLOW BIT(5)
94#define DCU_INT_MASK_P1FIFOLO BIT(6)
95#define DCU_INT_MASK_P1FIFOHI BIT(7)
96#define DCU_INT_MASK_P2FIFOLO BIT(8)
97#define DCU_INT_MASK_P2FIFOHI BIT(9)
98#define DCU_INT_MASK_PROGEND BIT(10)
99#define DCU_INT_MASK_IPMERROR BIT(11)
100#define DCU_INT_MASK_LYRTRANS BIT(12)
101#define DCU_INT_MASK_DMATRANS BIT(14)
102#define DCU_INT_MASK_P3FIFOLO BIT(16)
103#define DCU_INT_MASK_P3FIFOHI BIT(17)
104#define DCU_INT_MASK_P4FIFOLO BIT(18)
105#define DCU_INT_MASK_P4FIFOHI BIT(19)
106#define DCU_INT_MASK_P1EMPTY BIT(26)
107#define DCU_INT_MASK_P2EMPTY BIT(27)
108#define DCU_INT_MASK_P3EMPTY BIT(28)
109#define DCU_INT_MASK_P4EMPTY BIT(29)
110
111#define DCU_DIV_RATIO 0x0054
112
113#define DCU_UPDATE_MODE 0x00cc
114#define DCU_UPDATE_MODE_MODE BIT(31)
115#define DCU_UPDATE_MODE_READREG BIT(30)
116
117#define DCU_DCFB_MAX 0x300
118
119#define DCU_CTRLDESCLN(layer, reg) (0x200 + (reg - 1) * 4 + (layer) * 0x40)
120
121#define DCU_LAYER_HEIGHT(x) ((x) << 16)
122#define DCU_LAYER_WIDTH(x) (x)
123
124#define DCU_LAYER_POSY(x) ((x) << 16)
125#define DCU_LAYER_POSX(x) (x)
126
127#define DCU_LAYER_EN BIT(31)
128#define DCU_LAYER_TILE_EN BIT(30)
129#define DCU_LAYER_DATA_SEL_CLUT BIT(29)
130#define DCU_LAYER_SAFETY_EN BIT(28)
131#define DCU_LAYER_TRANS(x) ((x) << 20)
132#define DCU_LAYER_BPP(x) ((x) << 16)
133#define DCU_LAYER_RLE_EN BIT(15)
134#define DCU_LAYER_LUOFFS(x) ((x) << 4)
135#define DCU_LAYER_BB_ON BIT(2)
136#define DCU_LAYER_AB(x) (x)
137
138#define DCU_LAYER_CKMAX_R(x) ((x) << 16)
139#define DCU_LAYER_CKMAX_G(x) ((x) << 8)
140#define DCU_LAYER_CKMAX_B(x) (x)
141
142#define DCU_LAYER_CKMIN_R(x) ((x) << 16)
143#define DCU_LAYER_CKMIN_G(x) ((x) << 8)
144#define DCU_LAYER_CKMIN_B(x) (x)
145
146#define DCU_LAYER_TILE_VER(x) ((x) << 16)
147#define DCU_LAYER_TILE_HOR(x) (x)
148
149#define DCU_LAYER_FG_FCOLOR(x) (x)
150
151#define DCU_LAYER_BG_BCOLOR(x) (x)
152
153#define DCU_LAYER_POST_SKIP(x) ((x) << 16)
154#define DCU_LAYER_PRE_SKIP(x) (x)
155
156#define FSL_DCU_RGB565 4
157#define FSL_DCU_RGB888 5
158#define FSL_DCU_ARGB8888 6
159#define FSL_DCU_ARGB1555 11
160#define FSL_DCU_ARGB4444 12
161#define FSL_DCU_YUV422 14
162
163#define VF610_LAYER_REG_NUM 9
164#define LS1021A_LAYER_REG_NUM 10
165
166struct clk;
167struct device;
168struct drm_device;
169
170struct fsl_dcu_soc_data {
171 const char *name;
172 /*total layer number*/
173 unsigned int total_layer;
174 /*max layer number DCU supported*/
175 unsigned int max_layer;
176};
177
178struct fsl_dcu_drm_device {
179 struct device *dev;
180 struct device_node *np;
181 struct regmap *regmap;
182 int irq;
183 struct clk *clk;
184 /*protects hardware register*/
185 spinlock_t irq_lock;
186 struct drm_device *drm;
187 struct drm_fbdev_cma *fbdev;
188 struct drm_crtc crtc;
189 struct drm_encoder encoder;
190 struct fsl_dcu_drm_connector connector;
191 const struct fsl_dcu_soc_data *soc;
192};
193
194void fsl_dcu_fbdev_init(struct drm_device *dev);
195int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
196
197#endif /* __FSL_DCU_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c
new file mode 100644
index 000000000000..8b8b819ea704
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c
@@ -0,0 +1,23 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#include <drm/drmP.h>
13#include <drm/drm_fb_cma_helper.h>
14
15#include "fsl_dcu_drm_drv.h"
16
17/* initialize fbdev helper */
18void fsl_dcu_fbdev_init(struct drm_device *dev)
19{
20 struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
21
22 fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
23}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
new file mode 100644
index 000000000000..0ef5959710e7
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
@@ -0,0 +1,43 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#include <drm/drmP.h>
13#include <drm/drm_atomic_helper.h>
14#include <drm/drm_crtc_helper.h>
15#include <drm/drm_fb_cma_helper.h>
16
17#include "fsl_dcu_drm_crtc.h"
18#include "fsl_dcu_drm_drv.h"
19
20static const struct drm_mode_config_funcs fsl_dcu_drm_mode_config_funcs = {
21 .atomic_check = drm_atomic_helper_check,
22 .atomic_commit = drm_atomic_helper_commit,
23 .fb_create = drm_fb_cma_create,
24};
25
26int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev)
27{
28 drm_mode_config_init(fsl_dev->drm);
29
30 fsl_dev->drm->mode_config.min_width = 0;
31 fsl_dev->drm->mode_config.min_height = 0;
32 fsl_dev->drm->mode_config.max_width = 2031;
33 fsl_dev->drm->mode_config.max_height = 2047;
34 fsl_dev->drm->mode_config.funcs = &fsl_dcu_drm_mode_config_funcs;
35
36 drm_kms_helper_poll_init(fsl_dev->drm);
37 fsl_dcu_drm_crtc_create(fsl_dev);
38 fsl_dcu_drm_encoder_create(fsl_dev, &fsl_dev->crtc);
39 fsl_dcu_drm_connector_create(fsl_dev, &fsl_dev->encoder);
40 drm_mode_config_reset(fsl_dev->drm);
41
42 return 0;
43}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h
new file mode 100644
index 000000000000..7093109fbc21
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_output.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#ifndef __FSL_DCU_DRM_CONNECTOR_H__
13#define __FSL_DCU_DRM_CONNECTOR_H__
14
15struct fsl_dcu_drm_connector {
16 struct drm_connector base;
17 struct drm_encoder *encoder;
18 struct drm_panel *panel;
19};
20
21static inline struct fsl_dcu_drm_connector *
22to_fsl_dcu_connector(struct drm_connector *con)
23{
24 return con ? container_of(con, struct fsl_dcu_drm_connector, base)
25 : NULL;
26}
27
28int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
29 struct drm_encoder *encoder);
30int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
31 struct drm_crtc *crtc);
32
33#endif /* __FSL_DCU_DRM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
new file mode 100644
index 000000000000..82be6b86a168
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
@@ -0,0 +1,261 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#include <linux/regmap.h>
13
14#include <drm/drmP.h>
15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc.h>
17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_fb_cma_helper.h>
19#include <drm/drm_gem_cma_helper.h>
20#include <drm/drm_plane_helper.h>
21
22#include "fsl_dcu_drm_drv.h"
23#include "fsl_dcu_drm_plane.h"
24
25static int fsl_dcu_drm_plane_index(struct drm_plane *plane)
26{
27 struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
28 unsigned int total_layer = fsl_dev->soc->total_layer;
29 unsigned int index;
30
31 index = drm_plane_index(plane);
32 if (index < total_layer)
33 return total_layer - index - 1;
34
35 dev_err(fsl_dev->dev, "No more layer left\n");
36 return -EINVAL;
37}
38
39static int fsl_dcu_drm_plane_atomic_check(struct drm_plane *plane,
40 struct drm_plane_state *state)
41{
42 struct drm_framebuffer *fb = state->fb;
43
44 switch (fb->pixel_format) {
45 case DRM_FORMAT_RGB565:
46 case DRM_FORMAT_RGB888:
47 case DRM_FORMAT_ARGB8888:
48 case DRM_FORMAT_BGRA4444:
49 case DRM_FORMAT_ARGB1555:
50 case DRM_FORMAT_YUV422:
51 return 0;
52 default:
53 return -EINVAL;
54 }
55}
56
57static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
58 struct drm_plane_state *old_state)
59{
60 struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
61 unsigned int index, value, ret;
62
63 index = fsl_dcu_drm_plane_index(plane);
64 if (index < 0)
65 return;
66
67 ret = regmap_read(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), &value);
68 if (ret)
69 dev_err(fsl_dev->dev, "read DCU_INT_MASK failed\n");
70 value &= ~DCU_LAYER_EN;
71 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4), value);
72 if (ret)
73 dev_err(fsl_dev->dev, "set DCU register failed\n");
74}
75
76static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
77 struct drm_plane_state *old_state)
78
79{
80 struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
81 struct drm_plane_state *state = plane->state;
82 struct drm_framebuffer *fb = plane->state->fb;
83 struct drm_gem_cma_object *gem;
84 unsigned int alpha, bpp;
85 int index, ret;
86
87 if (!fb)
88 return;
89
90 index = fsl_dcu_drm_plane_index(plane);
91 if (index < 0)
92 return;
93
94 gem = drm_fb_cma_get_gem_obj(fb, 0);
95
96 switch (fb->pixel_format) {
97 case DRM_FORMAT_RGB565:
98 bpp = FSL_DCU_RGB565;
99 alpha = 0xff;
100 break;
101 case DRM_FORMAT_RGB888:
102 bpp = FSL_DCU_RGB888;
103 alpha = 0xff;
104 break;
105 case DRM_FORMAT_ARGB8888:
106 bpp = FSL_DCU_ARGB8888;
107 alpha = 0xff;
108 break;
109 case DRM_FORMAT_BGRA4444:
110 bpp = FSL_DCU_ARGB4444;
111 alpha = 0xff;
112 break;
113 case DRM_FORMAT_ARGB1555:
114 bpp = FSL_DCU_ARGB1555;
115 alpha = 0xff;
116 break;
117 case DRM_FORMAT_YUV422:
118 bpp = FSL_DCU_YUV422;
119 alpha = 0xff;
120 break;
121 default:
122 return;
123 }
124
125 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 1),
126 DCU_LAYER_HEIGHT(state->crtc_h) |
127 DCU_LAYER_WIDTH(state->crtc_w));
128 if (ret)
129 goto set_failed;
130 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 2),
131 DCU_LAYER_POSY(state->crtc_y) |
132 DCU_LAYER_POSX(state->crtc_x));
133 if (ret)
134 goto set_failed;
135 ret = regmap_write(fsl_dev->regmap,
136 DCU_CTRLDESCLN(index, 3), gem->paddr);
137 if (ret)
138 goto set_failed;
139 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
140 DCU_LAYER_EN |
141 DCU_LAYER_TRANS(alpha) |
142 DCU_LAYER_BPP(bpp) |
143 DCU_LAYER_AB(0));
144 if (ret)
145 goto set_failed;
146 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 5),
147 DCU_LAYER_CKMAX_R(0xFF) |
148 DCU_LAYER_CKMAX_G(0xFF) |
149 DCU_LAYER_CKMAX_B(0xFF));
150 if (ret)
151 goto set_failed;
152 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 6),
153 DCU_LAYER_CKMIN_R(0) |
154 DCU_LAYER_CKMIN_G(0) |
155 DCU_LAYER_CKMIN_B(0));
156 if (ret)
157 goto set_failed;
158 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 7), 0);
159 if (ret)
160 goto set_failed;
161 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 8),
162 DCU_LAYER_FG_FCOLOR(0));
163 if (ret)
164 goto set_failed;
165 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 9),
166 DCU_LAYER_BG_BCOLOR(0));
167 if (ret)
168 goto set_failed;
169 if (!strcmp(fsl_dev->soc->name, "ls1021a")) {
170 ret = regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 10),
171 DCU_LAYER_POST_SKIP(0) |
172 DCU_LAYER_PRE_SKIP(0));
173 if (ret)
174 goto set_failed;
175 }
176 ret = regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,
177 DCU_MODE_DCU_MODE_MASK,
178 DCU_MODE_DCU_MODE(DCU_MODE_NORMAL));
179 if (ret)
180 goto set_failed;
181 ret = regmap_write(fsl_dev->regmap,
182 DCU_UPDATE_MODE, DCU_UPDATE_MODE_READREG);
183 if (ret)
184 goto set_failed;
185 return;
186
187set_failed:
188 dev_err(fsl_dev->dev, "set DCU register failed\n");
189}
190
191static void
192fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
193 struct drm_framebuffer *fb,
194 const struct drm_plane_state *new_state)
195{
196}
197
198static int
199fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
200 struct drm_framebuffer *fb,
201 const struct drm_plane_state *new_state)
202{
203 return 0;
204}
205
206static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
207 .atomic_check = fsl_dcu_drm_plane_atomic_check,
208 .atomic_disable = fsl_dcu_drm_plane_atomic_disable,
209 .atomic_update = fsl_dcu_drm_plane_atomic_update,
210 .cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
211 .prepare_fb = fsl_dcu_drm_plane_prepare_fb,
212};
213
214static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
215{
216 drm_plane_cleanup(plane);
217}
218
219static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
220 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
221 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
222 .destroy = fsl_dcu_drm_plane_destroy,
223 .disable_plane = drm_atomic_helper_disable_plane,
224 .reset = drm_atomic_helper_plane_reset,
225 .update_plane = drm_atomic_helper_update_plane,
226};
227
228static const u32 fsl_dcu_drm_plane_formats[] = {
229 DRM_FORMAT_RGB565,
230 DRM_FORMAT_RGB888,
231 DRM_FORMAT_ARGB8888,
232 DRM_FORMAT_ARGB4444,
233 DRM_FORMAT_ARGB1555,
234 DRM_FORMAT_YUV422,
235};
236
237struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev)
238{
239 struct drm_plane *primary;
240 int ret;
241
242 primary = kzalloc(sizeof(*primary), GFP_KERNEL);
243 if (!primary) {
244 DRM_DEBUG_KMS("Failed to allocate primary plane\n");
245 return NULL;
246 }
247
248 /* possible_crtc's will be filled in later by crtc_init */
249 ret = drm_universal_plane_init(dev, primary, 0,
250 &fsl_dcu_drm_plane_funcs,
251 fsl_dcu_drm_plane_formats,
252 ARRAY_SIZE(fsl_dcu_drm_plane_formats),
253 DRM_PLANE_TYPE_PRIMARY);
254 if (ret) {
255 kfree(primary);
256 primary = NULL;
257 }
258 drm_plane_helper_add(primary, &fsl_dcu_drm_plane_helper_funcs);
259
260 return primary;
261}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
new file mode 100644
index 000000000000..d657f088d859
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.h
@@ -0,0 +1,17 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#ifndef __FSL_DCU_DRM_PLANE_H__
13#define __FSL_DCU_DRM_PLANE_H__
14
15struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev);
16
17#endif /* __FSL_DCU_DRM_PLANE_H__ */
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
new file mode 100644
index 000000000000..fe8ab5da04fb
--- /dev/null
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -0,0 +1,182 @@
1/*
2 * Copyright 2015 Freescale Semiconductor, Inc.
3 *
4 * Freescale DCU drm device driver
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
12#include <linux/backlight.h>
13
14#include <drm/drmP.h>
15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_panel.h>
18
19#include "fsl_dcu_drm_drv.h"
20
21static int
22fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
23 struct drm_crtc_state *crtc_state,
24 struct drm_connector_state *conn_state)
25{
26 return 0;
27}
28
29static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
30{
31}
32
33static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder)
34{
35}
36
37static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
38 .atomic_check = fsl_dcu_drm_encoder_atomic_check,
39 .disable = fsl_dcu_drm_encoder_disable,
40 .enable = fsl_dcu_drm_encoder_enable,
41};
42
43static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)
44{
45 drm_encoder_cleanup(encoder);
46}
47
48static const struct drm_encoder_funcs encoder_funcs = {
49 .destroy = fsl_dcu_drm_encoder_destroy,
50};
51
52int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
53 struct drm_crtc *crtc)
54{
55 struct drm_encoder *encoder = &fsl_dev->encoder;
56 int ret;
57
58 encoder->possible_crtcs = 1;
59 ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs,
60 DRM_MODE_ENCODER_LVDS);
61 if (ret < 0)
62 return ret;
63
64 drm_encoder_helper_add(encoder, &encoder_helper_funcs);
65
66 return 0;
67}
68
69static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
70{
71 drm_connector_unregister(connector);
72 drm_connector_cleanup(connector);
73}
74
75static enum drm_connector_status
76fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
77{
78 return connector_status_connected;
79}
80
81static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
82 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
83 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
84 .destroy = fsl_dcu_drm_connector_destroy,
85 .detect = fsl_dcu_drm_connector_detect,
86 .dpms = drm_atomic_helper_connector_dpms,
87 .fill_modes = drm_helper_probe_single_connector_modes,
88 .reset = drm_atomic_helper_connector_reset,
89};
90
91static struct drm_encoder *
92fsl_dcu_drm_connector_best_encoder(struct drm_connector *connector)
93{
94 struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
95
96 return fsl_con->encoder;
97}
98
99static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
100{
101 struct fsl_dcu_drm_connector *fsl_connector;
102 int (*get_modes)(struct drm_panel *panel);
103 int num_modes = 0;
104
105 fsl_connector = to_fsl_dcu_connector(connector);
106 if (fsl_connector->panel && fsl_connector->panel->funcs &&
107 fsl_connector->panel->funcs->get_modes) {
108 get_modes = fsl_connector->panel->funcs->get_modes;
109 num_modes = get_modes(fsl_connector->panel);
110 }
111
112 return num_modes;
113}
114
115static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
116 struct drm_display_mode *mode)
117{
118 if (mode->hdisplay & 0xf)
119 return MODE_ERROR;
120
121 return MODE_OK;
122}
123
124static const struct drm_connector_helper_funcs connector_helper_funcs = {
125 .best_encoder = fsl_dcu_drm_connector_best_encoder,
126 .get_modes = fsl_dcu_drm_connector_get_modes,
127 .mode_valid = fsl_dcu_drm_connector_mode_valid,
128};
129
130int fsl_dcu_drm_connector_create(struct fsl_dcu_drm_device *fsl_dev,
131 struct drm_encoder *encoder)
132{
133 struct drm_connector *connector = &fsl_dev->connector.base;
134 struct drm_mode_config mode_config = fsl_dev->drm->mode_config;
135 struct device_node *panel_node;
136 int ret;
137
138 fsl_dev->connector.encoder = encoder;
139
140 ret = drm_connector_init(fsl_dev->drm, connector,
141 &fsl_dcu_drm_connector_funcs,
142 DRM_MODE_CONNECTOR_LVDS);
143 if (ret < 0)
144 return ret;
145
146 drm_connector_helper_add(connector, &connector_helper_funcs);
147 ret = drm_connector_register(connector);
148 if (ret < 0)
149 goto err_cleanup;
150
151 ret = drm_mode_connector_attach_encoder(connector, encoder);
152 if (ret < 0)
153 goto err_sysfs;
154
155 drm_object_property_set_value(&connector->base,
156 mode_config.dpms_property,
157 DRM_MODE_DPMS_OFF);
158
159 panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0);
160 if (panel_node) {
161 fsl_dev->connector.panel = of_drm_find_panel(panel_node);
162 if (!fsl_dev->connector.panel) {
163 ret = -EPROBE_DEFER;
164 goto err_sysfs;
165 }
166 of_node_put(panel_node);
167 }
168
169 ret = drm_panel_attach(fsl_dev->connector.panel, connector);
170 if (ret) {
171 dev_err(fsl_dev->dev, "failed to attach panel\n");
172 goto err_sysfs;
173 }
174
175 return 0;
176
177err_sysfs:
178 drm_connector_unregister(connector);
179err_cleanup:
180 drm_connector_cleanup(connector);
181 return ret;
182}