aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2013-01-08 16:04:28 -0500
committerRob Clark <robdclark@gmail.com>2013-02-19 17:57:44 -0500
commit16ea975eac671fa40a78594a116a44fef8e3f4a9 (patch)
tree4e83f07ea5856e0b33e8fd0918f11aff4b25547b
parentb3d3de80133d32723224329f87edecaff230fefc (diff)
drm/tilcdc: add TI LCD Controller DRM driver (v4)
A simple DRM/KMS driver for the TI LCD Controller found in various smaller TI parts (AM33xx, OMAPL138, etc). This driver uses the CMA helpers. Currently only the TFP410 DVI encoder is supported (tested with beaglebone + DVI cape). There are also various LCD displays, for which support can be added (as I get hw to test on), and an external i2c HDMI encoder found on some boards. The display controller supports a single CRTC. And the encoder+ connector are split out into sub-devices. Depending on which LCD or external encoder is actually present, the appropriate output module(s) will be loaded. v1: original v2: fix fb refcnting and few other cleanups v3: get +/- vsync/hsync from timings rather than panel-info, add option DT max-bandwidth field so driver doesn't attempt to pick a display mode with too high memory bandwidth, and other small cleanups v4: remove some unneeded stuff from panel-info struct, properly set high bits for hfp/hsw/hbp for rev 2, add DT bindings docs Signed-off-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Tested-by: Koen Kooi <koen@dominion.thruhere.net>
-rw-r--r--Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt21
-rw-r--r--Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt21
-rw-r--r--drivers/gpu/drm/Kconfig2
-rw-r--r--drivers/gpu/drm/Makefile1
-rw-r--r--drivers/gpu/drm/tilcdc/Kconfig10
-rw-r--r--drivers/gpu/drm/tilcdc/Makefile8
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c602
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c605
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h150
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_regs.h154
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.c419
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.h26
12 files changed, 2019 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt b/Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt
new file mode 100644
index 000000000000..a58ae7756fc6
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt
@@ -0,0 +1,21 @@
1Device-Tree bindings for tilcdc DRM TFP410 output driver
2
3Required properties:
4 - compatible: value should be "ti,tilcdc,tfp410".
5 - i2c: the phandle for the i2c device to use for DDC
6
7Recommended properties:
8 - pinctrl-names, pinctrl-0: the pincontrol settings to configure
9 muxing properly for pins that connect to TFP410 device
10 - powerdn-gpio: the powerdown GPIO, pulled low to power down the
11 TFP410 device (for DPMS_OFF)
12
13Example:
14
15 dvicape {
16 compatible = "ti,tilcdc,tfp410";
17 i2c = <&i2c2>;
18 pinctrl-names = "default";
19 pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>;
20 powerdn-gpio = <&gpio2 31 0>;
21 };
diff --git a/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt
new file mode 100644
index 000000000000..e5f130159ae1
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt
@@ -0,0 +1,21 @@
1Device-Tree bindings for tilcdc DRM driver
2
3Required properties:
4 - compatible: value should be "ti,am33xx-tilcdc".
5 - interrupts: the interrupt number
6 - reg: base address and size of the LCDC device
7
8Recommended properties:
9 - interrupt-parent: the phandle for the interrupt controller that
10 services interrupts for this device.
11 - ti,hwmods: Name of the hwmod associated to the LCDC
12
13Example:
14
15 fb: fb@4830e000 {
16 compatible = "ti,am33xx-tilcdc";
17 reg = <0x4830e000 0x1000>;
18 interrupt-parent = <&intc>;
19 interrupts = <36>;
20 ti,hwmods = "lcdc";
21 };
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index ed9e3af17b31..ba74e75f7d54 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -215,3 +215,5 @@ source "drivers/gpu/drm/cirrus/Kconfig"
215source "drivers/gpu/drm/shmobile/Kconfig" 215source "drivers/gpu/drm/shmobile/Kconfig"
216 216
217source "drivers/gpu/drm/tegra/Kconfig" 217source "drivers/gpu/drm/tegra/Kconfig"
218
219source "drivers/gpu/drm/tilcdc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 6f58c81cfcbc..3af934dffe68 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -50,4 +50,5 @@ obj-$(CONFIG_DRM_UDL) += udl/
50obj-$(CONFIG_DRM_AST) += ast/ 50obj-$(CONFIG_DRM_AST) += ast/
51obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/ 51obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
52obj-$(CONFIG_DRM_TEGRA) += tegra/ 52obj-$(CONFIG_DRM_TEGRA) += tegra/
53obj-$(CONFIG_DRM_TILCDC) += tilcdc/
53obj-y += i2c/ 54obj-y += i2c/
diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
new file mode 100644
index 000000000000..ee9b592d59eb
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/Kconfig
@@ -0,0 +1,10 @@
1config DRM_TILCDC
2 tristate "DRM Support for TI LCDC Display Controller"
3 depends on DRM && OF
4 select DRM_KMS_HELPER
5 select DRM_KMS_CMA_HELPER
6 select DRM_GEM_CMA_HELPER
7 help
8 Choose this option if you have an TI SoC with LCDC display
9 controller, for example AM33xx in beagle-bone, DA8xx, or
10 OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver.
diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile
new file mode 100644
index 000000000000..1359cc29cd81
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/Makefile
@@ -0,0 +1,8 @@
1ccflags-y := -Iinclude/drm -Werror
2
3tilcdc-y := \
4 tilcdc_crtc.o \
5 tilcdc_tfp410.o \
6 tilcdc_drv.o
7
8obj-$(CONFIG_DRM_TILCDC) += tilcdc.o
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
new file mode 100644
index 000000000000..5dd3c7d031d5
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -0,0 +1,602 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/kfifo.h>
19
20#include "tilcdc_drv.h"
21#include "tilcdc_regs.h"
22
23struct tilcdc_crtc {
24 struct drm_crtc base;
25
26 const struct tilcdc_panel_info *info;
27 uint32_t dirty;
28 dma_addr_t start, end;
29 struct drm_pending_vblank_event *event;
30 int dpms;
31 wait_queue_head_t frame_done_wq;
32 bool frame_done;
33
34 /* fb currently set to scanout 0/1: */
35 struct drm_framebuffer *scanout[2];
36
37 /* for deferred fb unref's: */
38 DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *);
39 struct work_struct work;
40};
41#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
42
43static void unref_worker(struct work_struct *work)
44{
45 struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work);
46 struct drm_device *dev = tilcdc_crtc->base.dev;
47 struct drm_framebuffer *fb;
48
49 mutex_lock(&dev->mode_config.mutex);
50 while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb))
51 drm_framebuffer_unreference(fb);
52 mutex_unlock(&dev->mode_config.mutex);
53}
54
55static void set_scanout(struct drm_crtc *crtc, int n)
56{
57 static const uint32_t base_reg[] = {
58 LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG,
59 };
60 static const uint32_t ceil_reg[] = {
61 LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG,
62 };
63 static const uint32_t stat[] = {
64 LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1,
65 };
66 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
67 struct drm_device *dev = crtc->dev;
68
69 pm_runtime_get_sync(dev->dev);
70 tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
71 tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
72 if (tilcdc_crtc->scanout[n]) {
73 if (kfifo_put(&tilcdc_crtc->unref_fifo,
74 (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) {
75 struct tilcdc_drm_private *priv = dev->dev_private;
76 queue_work(priv->wq, &tilcdc_crtc->work);
77 } else {
78 dev_err(dev->dev, "unref fifo full!\n");
79 drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
80 }
81 }
82 tilcdc_crtc->scanout[n] = crtc->fb;
83 drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
84 tilcdc_crtc->dirty &= ~stat[n];
85 pm_runtime_put_sync(dev->dev);
86}
87
88static void update_scanout(struct drm_crtc *crtc)
89{
90 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
91 struct drm_device *dev = crtc->dev;
92 struct drm_framebuffer *fb = crtc->fb;
93 struct drm_gem_cma_object *gem;
94 unsigned int depth, bpp;
95
96 drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
97 gem = drm_fb_cma_get_gem_obj(fb, 0);
98
99 tilcdc_crtc->start = gem->paddr + fb->offsets[0] +
100 (crtc->y * fb->pitches[0]) + (crtc->x * bpp/8);
101
102 tilcdc_crtc->end = tilcdc_crtc->start +
103 (crtc->mode.vdisplay * fb->pitches[0]);
104
105 if (tilcdc_crtc->dpms == DRM_MODE_DPMS_ON) {
106 /* already enabled, so just mark the frames that need
107 * updating and they will be updated on vblank:
108 */
109 tilcdc_crtc->dirty |= LCDC_END_OF_FRAME0 | LCDC_END_OF_FRAME1;
110 drm_vblank_get(dev, 0);
111 } else {
112 /* not enabled yet, so update registers immediately: */
113 set_scanout(crtc, 0);
114 set_scanout(crtc, 1);
115 }
116}
117
118static void start(struct drm_crtc *crtc)
119{
120 struct drm_device *dev = crtc->dev;
121 struct tilcdc_drm_private *priv = dev->dev_private;
122
123 if (priv->rev == 2) {
124 tilcdc_set(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
125 msleep(1);
126 tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
127 msleep(1);
128 }
129
130 tilcdc_set(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
131 tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY));
132 tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
133}
134
135static void stop(struct drm_crtc *crtc)
136{
137 struct drm_device *dev = crtc->dev;
138
139 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
140}
141
142static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
143{
144 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
145
146 WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
147
148 drm_crtc_cleanup(crtc);
149 WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo));
150 kfifo_free(&tilcdc_crtc->unref_fifo);
151 kfree(tilcdc_crtc);
152}
153
154static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
155 struct drm_framebuffer *fb,
156 struct drm_pending_vblank_event *event)
157{
158 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
159 struct drm_device *dev = crtc->dev;
160
161 if (tilcdc_crtc->event) {
162 dev_err(dev->dev, "already pending page flip!\n");
163 return -EBUSY;
164 }
165
166 crtc->fb = fb;
167 tilcdc_crtc->event = event;
168 update_scanout(crtc);
169
170 return 0;
171}
172
173static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode)
174{
175 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
176 struct drm_device *dev = crtc->dev;
177 struct tilcdc_drm_private *priv = dev->dev_private;
178
179 /* we really only care about on or off: */
180 if (mode != DRM_MODE_DPMS_ON)
181 mode = DRM_MODE_DPMS_OFF;
182
183 if (tilcdc_crtc->dpms == mode)
184 return;
185
186 tilcdc_crtc->dpms = mode;
187
188 pm_runtime_get_sync(dev->dev);
189
190 if (mode == DRM_MODE_DPMS_ON) {
191 pm_runtime_forbid(dev->dev);
192 start(crtc);
193 } else {
194 tilcdc_crtc->frame_done = false;
195 stop(crtc);
196
197 /* if necessary wait for framedone irq which will still come
198 * before putting things to sleep..
199 */
200 if (priv->rev == 2) {
201 int ret = wait_event_timeout(
202 tilcdc_crtc->frame_done_wq,
203 tilcdc_crtc->frame_done,
204 msecs_to_jiffies(50));
205 if (ret == 0)
206 dev_err(dev->dev, "timeout waiting for framedone\n");
207 }
208 pm_runtime_allow(dev->dev);
209 }
210
211 pm_runtime_put_sync(dev->dev);
212}
213
214static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
215 const struct drm_display_mode *mode,
216 struct drm_display_mode *adjusted_mode)
217{
218 return true;
219}
220
221static void tilcdc_crtc_prepare(struct drm_crtc *crtc)
222{
223 tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
224}
225
226static void tilcdc_crtc_commit(struct drm_crtc *crtc)
227{
228 tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
229}
230
231static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
232 struct drm_display_mode *mode,
233 struct drm_display_mode *adjusted_mode,
234 int x, int y,
235 struct drm_framebuffer *old_fb)
236{
237 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
238 struct drm_device *dev = crtc->dev;
239 struct tilcdc_drm_private *priv = dev->dev_private;
240 const struct tilcdc_panel_info *info = tilcdc_crtc->info;
241 uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw;
242 int ret;
243
244 ret = tilcdc_crtc_mode_valid(crtc, mode);
245 if (WARN_ON(ret))
246 return ret;
247
248 if (WARN_ON(!info))
249 return -EINVAL;
250
251 pm_runtime_get_sync(dev->dev);
252
253 /* Configure the Burst Size and fifo threshold of DMA: */
254 reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770;
255 switch (info->dma_burst_sz) {
256 case 1:
257 reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1);
258 break;
259 case 2:
260 reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2);
261 break;
262 case 4:
263 reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4);
264 break;
265 case 8:
266 reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8);
267 break;
268 case 16:
269 reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16);
270 break;
271 default:
272 return -EINVAL;
273 }
274 reg |= (info->fifo_th << 8);
275 tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg);
276
277 /* Configure timings: */
278 hbp = mode->htotal - mode->hsync_end;
279 hfp = mode->hsync_start - mode->hdisplay;
280 hsw = mode->hsync_end - mode->hsync_start;
281 vbp = mode->vtotal - mode->vsync_end;
282 vfp = mode->vsync_start - mode->vdisplay;
283 vsw = mode->vsync_end - mode->vsync_start;
284
285 DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u",
286 mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw);
287
288 /* Configure the AC Bias Period and Number of Transitions per Interrupt: */
289 reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00;
290 reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) |
291 LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt);
292 if (priv->rev == 2) {
293 reg |= (hfp & 0x300) >> 8;
294 reg |= (hbp & 0x300) >> 4;
295 reg |= (hsw & 0x3c0) << 21;
296 }
297 tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg);
298
299 reg = (((mode->hdisplay >> 4) - 1) << 4) |
300 ((hbp & 0xff) << 24) |
301 ((hfp & 0xff) << 16) |
302 ((hsw & 0x3f) << 10);
303 if (priv->rev == 2)
304 reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3;
305 tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg);
306
307 reg = ((mode->vdisplay - 1) & 0x3ff) |
308 ((vbp & 0xff) << 24) |
309 ((vfp & 0xff) << 16) |
310 ((vsw & 0x3f) << 10);
311 tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg);
312
313 /* Configure display type: */
314 reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) &
315 ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE |
316 LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000);
317 reg |= LCDC_TFT_MODE; /* no monochrome/passive support */
318 if (info->tft_alt_mode)
319 reg |= LCDC_TFT_ALT_ENABLE;
320 if (priv->rev == 2) {
321 unsigned int depth, bpp;
322
323 drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp);
324 switch (bpp) {
325 case 16:
326 break;
327 case 32:
328 reg |= LCDC_V2_TFT_24BPP_UNPACK;
329 /* fallthrough */
330 case 24:
331 reg |= LCDC_V2_TFT_24BPP_MODE;
332 break;
333 default:
334 dev_err(dev->dev, "invalid pixel format\n");
335 return -EINVAL;
336 }
337 }
338 reg |= info->fdd < 12;
339 tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg);
340
341 if (info->invert_pxl_clk)
342 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
343 else
344 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK);
345
346 if (info->sync_ctrl)
347 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
348 else
349 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL);
350
351 if (info->sync_edge)
352 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
353 else
354 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
355
356 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
357 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
358 else
359 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
360
361 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
362 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
363 else
364 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC);
365
366 if (info->raster_order)
367 tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
368 else
369 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
370
371
372 update_scanout(crtc);
373 tilcdc_crtc_update_clk(crtc);
374
375 pm_runtime_put_sync(dev->dev);
376
377 return 0;
378}
379
380static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
381 struct drm_framebuffer *old_fb)
382{
383 update_scanout(crtc);
384 return 0;
385}
386
387static void tilcdc_crtc_load_lut(struct drm_crtc *crtc)
388{
389}
390
391static const struct drm_crtc_funcs tilcdc_crtc_funcs = {
392 .destroy = tilcdc_crtc_destroy,
393 .set_config = drm_crtc_helper_set_config,
394 .page_flip = tilcdc_crtc_page_flip,
395};
396
397static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = {
398 .dpms = tilcdc_crtc_dpms,
399 .mode_fixup = tilcdc_crtc_mode_fixup,
400 .prepare = tilcdc_crtc_prepare,
401 .commit = tilcdc_crtc_commit,
402 .mode_set = tilcdc_crtc_mode_set,
403 .mode_set_base = tilcdc_crtc_mode_set_base,
404 .load_lut = tilcdc_crtc_load_lut,
405};
406
407int tilcdc_crtc_max_width(struct drm_crtc *crtc)
408{
409 struct drm_device *dev = crtc->dev;
410 struct tilcdc_drm_private *priv = dev->dev_private;
411 int max_width = 0;
412
413 if (priv->rev == 1)
414 max_width = 1024;
415 else if (priv->rev == 2)
416 max_width = 2048;
417
418 return max_width;
419}
420
421int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode)
422{
423 struct tilcdc_drm_private *priv = crtc->dev->dev_private;
424 unsigned int bandwidth;
425
426 if (mode->hdisplay > tilcdc_crtc_max_width(crtc))
427 return MODE_VIRTUAL_X;
428
429 /* width must be multiple of 16 */
430 if (mode->hdisplay & 0xf)
431 return MODE_VIRTUAL_X;
432
433 if (mode->vdisplay > 2048)
434 return MODE_VIRTUAL_Y;
435
436 /* filter out modes that would require too much memory bandwidth: */
437 bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode);
438 if (bandwidth > priv->max_bandwidth)
439 return MODE_BAD;
440
441 return MODE_OK;
442}
443
444void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
445 const struct tilcdc_panel_info *info)
446{
447 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
448 tilcdc_crtc->info = info;
449}
450
451void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
452{
453 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
454 struct drm_device *dev = crtc->dev;
455 struct tilcdc_drm_private *priv = dev->dev_private;
456 int dpms = tilcdc_crtc->dpms;
457 unsigned int lcd_clk, div;
458 int ret;
459
460 pm_runtime_get_sync(dev->dev);
461
462 if (dpms == DRM_MODE_DPMS_ON)
463 tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
464
465 /* in raster mode, minimum divisor is 2: */
466 ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2);
467 if (ret) {
468 dev_err(dev->dev, "failed to set display clock rate to: %d\n",
469 crtc->mode.clock);
470 goto out;
471 }
472
473 lcd_clk = clk_get_rate(priv->clk);
474 div = lcd_clk / (crtc->mode.clock * 1000);
475
476 DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div);
477 DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk));
478
479 /* Configure the LCD clock divisor. */
480 tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) |
481 LCDC_RASTER_MODE);
482
483 if (priv->rev == 2)
484 tilcdc_set(dev, LCDC_CLK_ENABLE_REG,
485 LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN |
486 LCDC_V2_CORE_CLK_EN);
487
488 if (dpms == DRM_MODE_DPMS_ON)
489 tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
490
491out:
492 pm_runtime_put_sync(dev->dev);
493}
494
495irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
496{
497 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
498 struct drm_device *dev = crtc->dev;
499 struct tilcdc_drm_private *priv = dev->dev_private;
500 uint32_t stat = tilcdc_read_irqstatus(dev);
501
502 if ((stat & LCDC_SYNC_LOST) && (stat & LCDC_FIFO_UNDERFLOW)) {
503 stop(crtc);
504 dev_err(dev->dev, "error: %08x\n", stat);
505 tilcdc_clear_irqstatus(dev, stat);
506 start(crtc);
507 } else if (stat & LCDC_PL_LOAD_DONE) {
508 tilcdc_clear_irqstatus(dev, stat);
509 } else {
510 struct drm_pending_vblank_event *event;
511 unsigned long flags;
512 uint32_t dirty = tilcdc_crtc->dirty & stat;
513
514 tilcdc_clear_irqstatus(dev, stat);
515
516 if (dirty & LCDC_END_OF_FRAME0)
517 set_scanout(crtc, 0);
518
519 if (dirty & LCDC_END_OF_FRAME1)
520 set_scanout(crtc, 1);
521
522 drm_handle_vblank(dev, 0);
523
524 spin_lock_irqsave(&dev->event_lock, flags);
525 event = tilcdc_crtc->event;
526 tilcdc_crtc->event = NULL;
527 if (event)
528 drm_send_vblank_event(dev, 0, event);
529 spin_unlock_irqrestore(&dev->event_lock, flags);
530
531 if (dirty && !tilcdc_crtc->dirty)
532 drm_vblank_put(dev, 0);
533 }
534
535 if (priv->rev == 2) {
536 if (stat & LCDC_FRAME_DONE) {
537 tilcdc_crtc->frame_done = true;
538 wake_up(&tilcdc_crtc->frame_done_wq);
539 }
540 tilcdc_write(dev, LCDC_END_OF_INT_IND_REG, 0);
541 }
542
543 return IRQ_HANDLED;
544}
545
546void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file)
547{
548 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
549 struct drm_pending_vblank_event *event;
550 struct drm_device *dev = crtc->dev;
551 unsigned long flags;
552
553 /* Destroy the pending vertical blanking event associated with the
554 * pending page flip, if any, and disable vertical blanking interrupts.
555 */
556 spin_lock_irqsave(&dev->event_lock, flags);
557 event = tilcdc_crtc->event;
558 if (event && event->base.file_priv == file) {
559 tilcdc_crtc->event = NULL;
560 event->base.destroy(&event->base);
561 drm_vblank_put(dev, 0);
562 }
563 spin_unlock_irqrestore(&dev->event_lock, flags);
564}
565
566struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
567{
568 struct tilcdc_crtc *tilcdc_crtc;
569 struct drm_crtc *crtc;
570 int ret;
571
572 tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL);
573 if (!tilcdc_crtc) {
574 dev_err(dev->dev, "allocation failed\n");
575 return NULL;
576 }
577
578 crtc = &tilcdc_crtc->base;
579
580 tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
581 init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
582
583 ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL);
584 if (ret) {
585 dev_err(dev->dev, "could not allocate unref FIFO\n");
586 goto fail;
587 }
588
589 INIT_WORK(&tilcdc_crtc->work, unref_worker);
590
591 ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
592 if (ret < 0)
593 goto fail;
594
595 drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs);
596
597 return crtc;
598
599fail:
600 tilcdc_crtc_destroy(crtc);
601 return NULL;
602}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
new file mode 100644
index 000000000000..f6defbfaaffb
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -0,0 +1,605 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/* LCDC DRM driver, based on da8xx-fb */
19
20#include "tilcdc_drv.h"
21#include "tilcdc_regs.h"
22#include "tilcdc_tfp410.h"
23
24#include "drm_fb_helper.h"
25
26static LIST_HEAD(module_list);
27
28void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
29 const struct tilcdc_module_ops *funcs)
30{
31 mod->name = name;
32 mod->funcs = funcs;
33 INIT_LIST_HEAD(&mod->list);
34 list_add(&mod->list, &module_list);
35}
36
37void tilcdc_module_cleanup(struct tilcdc_module *mod)
38{
39 list_del(&mod->list);
40}
41
42static struct of_device_id tilcdc_of_match[];
43
44static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
45 struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
46{
47 return drm_fb_cma_create(dev, file_priv, mode_cmd);
48}
49
50static void tilcdc_fb_output_poll_changed(struct drm_device *dev)
51{
52 struct tilcdc_drm_private *priv = dev->dev_private;
53 if (priv->fbdev)
54 drm_fbdev_cma_hotplug_event(priv->fbdev);
55}
56
57static const struct drm_mode_config_funcs mode_config_funcs = {
58 .fb_create = tilcdc_fb_create,
59 .output_poll_changed = tilcdc_fb_output_poll_changed,
60};
61
62static int modeset_init(struct drm_device *dev)
63{
64 struct tilcdc_drm_private *priv = dev->dev_private;
65 struct tilcdc_module *mod;
66
67 drm_mode_config_init(dev);
68
69 priv->crtc = tilcdc_crtc_create(dev);
70
71 list_for_each_entry(mod, &module_list, list) {
72 DBG("loading module: %s", mod->name);
73 mod->funcs->modeset_init(mod, dev);
74 }
75
76 if ((priv->num_encoders = 0) || (priv->num_connectors == 0)) {
77 /* oh nos! */
78 dev_err(dev->dev, "no encoders/connectors found\n");
79 return -ENXIO;
80 }
81
82 dev->mode_config.min_width = 0;
83 dev->mode_config.min_height = 0;
84 dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
85 dev->mode_config.max_height = 2048;
86 dev->mode_config.funcs = &mode_config_funcs;
87
88 return 0;
89}
90
91#ifdef CONFIG_CPU_FREQ
92static int cpufreq_transition(struct notifier_block *nb,
93 unsigned long val, void *data)
94{
95 struct tilcdc_drm_private *priv = container_of(nb,
96 struct tilcdc_drm_private, freq_transition);
97 if (val == CPUFREQ_POSTCHANGE) {
98 if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) {
99 priv->lcd_fck_rate = clk_get_rate(priv->clk);
100 tilcdc_crtc_update_clk(priv->crtc);
101 }
102 }
103
104 return 0;
105}
106#endif
107
108/*
109 * DRM operations:
110 */
111
112static int tilcdc_unload(struct drm_device *dev)
113{
114 struct tilcdc_drm_private *priv = dev->dev_private;
115 struct tilcdc_module *mod, *cur;
116
117 drm_kms_helper_poll_fini(dev);
118 drm_mode_config_cleanup(dev);
119 drm_vblank_cleanup(dev);
120
121 pm_runtime_get_sync(dev->dev);
122 drm_irq_uninstall(dev);
123 pm_runtime_put_sync(dev->dev);
124
125#ifdef CONFIG_CPU_FREQ
126 cpufreq_unregister_notifier(&priv->freq_transition,
127 CPUFREQ_TRANSITION_NOTIFIER);
128#endif
129
130 if (priv->clk)
131 clk_put(priv->clk);
132
133 if (priv->mmio)
134 iounmap(priv->mmio);
135
136 flush_workqueue(priv->wq);
137 destroy_workqueue(priv->wq);
138
139 dev->dev_private = NULL;
140
141 pm_runtime_disable(dev->dev);
142
143 list_for_each_entry_safe(mod, cur, &module_list, list) {
144 DBG("destroying module: %s", mod->name);
145 mod->funcs->destroy(mod);
146 }
147
148 kfree(priv);
149
150 return 0;
151}
152
153static int tilcdc_load(struct drm_device *dev, unsigned long flags)
154{
155 struct platform_device *pdev = dev->platformdev;
156 struct device_node *node = pdev->dev.of_node;
157 struct tilcdc_drm_private *priv;
158 struct resource *res;
159 int ret;
160
161 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
162 if (!priv) {
163 dev_err(dev->dev, "failed to allocate private data\n");
164 return -ENOMEM;
165 }
166
167 dev->dev_private = priv;
168
169 priv->wq = alloc_ordered_workqueue("tilcdc", 0);
170
171 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
172 if (!res) {
173 dev_err(dev->dev, "failed to get memory resource\n");
174 ret = -EINVAL;
175 goto fail;
176 }
177
178 priv->mmio = ioremap_nocache(res->start, resource_size(res));
179 if (!priv->mmio) {
180 dev_err(dev->dev, "failed to ioremap\n");
181 ret = -ENOMEM;
182 goto fail;
183 }
184
185 priv->clk = clk_get(dev->dev, "fck");
186 if (IS_ERR(priv->clk)) {
187 dev_err(dev->dev, "failed to get functional clock\n");
188 ret = -ENODEV;
189 goto fail;
190 }
191
192 priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck");
193 if (IS_ERR(priv->clk)) {
194 dev_err(dev->dev, "failed to get display clock\n");
195 ret = -ENODEV;
196 goto fail;
197 }
198
199#ifdef CONFIG_CPU_FREQ
200 priv->lcd_fck_rate = clk_get_rate(priv->clk);
201 priv->freq_transition.notifier_call = cpufreq_transition;
202 ret = cpufreq_register_notifier(&priv->freq_transition,
203 CPUFREQ_TRANSITION_NOTIFIER);
204 if (ret) {
205 dev_err(dev->dev, "failed to register cpufreq notifier\n");
206 goto fail;
207 }
208#endif
209
210 if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth))
211 priv->max_bandwidth = 1280 * 1024 * 60;
212
213 pm_runtime_enable(dev->dev);
214
215 /* Determine LCD IP Version */
216 pm_runtime_get_sync(dev->dev);
217 switch (tilcdc_read(dev, LCDC_PID_REG)) {
218 case 0x4c100102:
219 priv->rev = 1;
220 break;
221 case 0x4f200800:
222 case 0x4f201000:
223 priv->rev = 2;
224 break;
225 default:
226 dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, "
227 "defaulting to LCD revision 1\n",
228 tilcdc_read(dev, LCDC_PID_REG));
229 priv->rev = 1;
230 break;
231 }
232
233 pm_runtime_put_sync(dev->dev);
234
235 ret = modeset_init(dev);
236 if (ret < 0) {
237 dev_err(dev->dev, "failed to initialize mode setting\n");
238 goto fail;
239 }
240
241 ret = drm_vblank_init(dev, 1);
242 if (ret < 0) {
243 dev_err(dev->dev, "failed to initialize vblank\n");
244 goto fail;
245 }
246
247 pm_runtime_get_sync(dev->dev);
248 ret = drm_irq_install(dev);
249 pm_runtime_put_sync(dev->dev);
250 if (ret < 0) {
251 dev_err(dev->dev, "failed to install IRQ handler\n");
252 goto fail;
253 }
254
255 platform_set_drvdata(pdev, dev);
256
257 priv->fbdev = drm_fbdev_cma_init(dev, 16,
258 dev->mode_config.num_crtc,
259 dev->mode_config.num_connector);
260
261 drm_kms_helper_poll_init(dev);
262
263 return 0;
264
265fail:
266 tilcdc_unload(dev);
267 return ret;
268}
269
270static void tilcdc_preclose(struct drm_device *dev, struct drm_file *file)
271{
272 struct tilcdc_drm_private *priv = dev->dev_private;
273
274 tilcdc_crtc_cancel_page_flip(priv->crtc, file);
275}
276
277static void tilcdc_lastclose(struct drm_device *dev)
278{
279 struct tilcdc_drm_private *priv = dev->dev_private;
280 drm_fbdev_cma_restore_mode(priv->fbdev);
281}
282
283static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
284{
285 struct drm_device *dev = arg;
286 struct tilcdc_drm_private *priv = dev->dev_private;
287 return tilcdc_crtc_irq(priv->crtc);
288}
289
290static void tilcdc_irq_preinstall(struct drm_device *dev)
291{
292 tilcdc_clear_irqstatus(dev, 0xffffffff);
293}
294
295static int tilcdc_irq_postinstall(struct drm_device *dev)
296{
297 struct tilcdc_drm_private *priv = dev->dev_private;
298
299 /* enable FIFO underflow irq: */
300 if (priv->rev == 1) {
301 tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_UNDERFLOW_INT_ENA);
302 } else {
303 tilcdc_set(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_UNDERFLOW_INT_ENA);
304 }
305
306 return 0;
307}
308
309static void tilcdc_irq_uninstall(struct drm_device *dev)
310{
311 struct tilcdc_drm_private *priv = dev->dev_private;
312
313 /* disable irqs that we might have enabled: */
314 if (priv->rev == 1) {
315 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
316 LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
317 tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA);
318 } else {
319 tilcdc_clear(dev, LCDC_INT_ENABLE_SET_REG,
320 LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA |
321 LCDC_V2_END_OF_FRAME0_INT_ENA | LCDC_V2_END_OF_FRAME1_INT_ENA |
322 LCDC_FRAME_DONE);
323 }
324
325}
326
327static void enable_vblank(struct drm_device *dev, bool enable)
328{
329 struct tilcdc_drm_private *priv = dev->dev_private;
330 u32 reg, mask;
331
332 if (priv->rev == 1) {
333 reg = LCDC_DMA_CTRL_REG;
334 mask = LCDC_V1_END_OF_FRAME_INT_ENA;
335 } else {
336 reg = LCDC_INT_ENABLE_SET_REG;
337 mask = LCDC_V2_END_OF_FRAME0_INT_ENA |
338 LCDC_V2_END_OF_FRAME1_INT_ENA | LCDC_FRAME_DONE;
339 }
340
341 if (enable)
342 tilcdc_set(dev, reg, mask);
343 else
344 tilcdc_clear(dev, reg, mask);
345}
346
347static int tilcdc_enable_vblank(struct drm_device *dev, int crtc)
348{
349 enable_vblank(dev, true);
350 return 0;
351}
352
353static void tilcdc_disable_vblank(struct drm_device *dev, int crtc)
354{
355 enable_vblank(dev, false);
356}
357
358#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_PM_SLEEP)
359static const struct {
360 const char *name;
361 uint8_t rev;
362 uint8_t save;
363 uint32_t reg;
364} registers[] = {
365#define REG(rev, save, reg) { #reg, rev, save, reg }
366 /* exists in revision 1: */
367 REG(1, false, LCDC_PID_REG),
368 REG(1, true, LCDC_CTRL_REG),
369 REG(1, false, LCDC_STAT_REG),
370 REG(1, true, LCDC_RASTER_CTRL_REG),
371 REG(1, true, LCDC_RASTER_TIMING_0_REG),
372 REG(1, true, LCDC_RASTER_TIMING_1_REG),
373 REG(1, true, LCDC_RASTER_TIMING_2_REG),
374 REG(1, true, LCDC_DMA_CTRL_REG),
375 REG(1, true, LCDC_DMA_FB_BASE_ADDR_0_REG),
376 REG(1, true, LCDC_DMA_FB_CEILING_ADDR_0_REG),
377 REG(1, true, LCDC_DMA_FB_BASE_ADDR_1_REG),
378 REG(1, true, LCDC_DMA_FB_CEILING_ADDR_1_REG),
379 /* new in revision 2: */
380 REG(2, false, LCDC_RAW_STAT_REG),
381 REG(2, false, LCDC_MASKED_STAT_REG),
382 REG(2, false, LCDC_INT_ENABLE_SET_REG),
383 REG(2, false, LCDC_INT_ENABLE_CLR_REG),
384 REG(2, false, LCDC_END_OF_INT_IND_REG),
385 REG(2, true, LCDC_CLK_ENABLE_REG),
386 REG(2, true, LCDC_INT_ENABLE_SET_REG),
387#undef REG
388};
389#endif
390
391#ifdef CONFIG_DEBUG_FS
392static int tilcdc_regs_show(struct seq_file *m, void *arg)
393{
394 struct drm_info_node *node = (struct drm_info_node *) m->private;
395 struct drm_device *dev = node->minor->dev;
396 struct tilcdc_drm_private *priv = dev->dev_private;
397 unsigned i;
398
399 pm_runtime_get_sync(dev->dev);
400
401 seq_printf(m, "revision: %d\n", priv->rev);
402
403 for (i = 0; i < ARRAY_SIZE(registers); i++)
404 if (priv->rev >= registers[i].rev)
405 seq_printf(m, "%s:\t %08x\n", registers[i].name,
406 tilcdc_read(dev, registers[i].reg));
407
408 pm_runtime_put_sync(dev->dev);
409
410 return 0;
411}
412
413static int tilcdc_mm_show(struct seq_file *m, void *arg)
414{
415 struct drm_info_node *node = (struct drm_info_node *) m->private;
416 struct drm_device *dev = node->minor->dev;
417 return drm_mm_dump_table(m, dev->mm_private);
418}
419
420static struct drm_info_list tilcdc_debugfs_list[] = {
421 { "regs", tilcdc_regs_show, 0 },
422 { "mm", tilcdc_mm_show, 0 },
423 { "fb", drm_fb_cma_debugfs_show, 0 },
424};
425
426static int tilcdc_debugfs_init(struct drm_minor *minor)
427{
428 struct drm_device *dev = minor->dev;
429 struct tilcdc_module *mod;
430 int ret;
431
432 ret = drm_debugfs_create_files(tilcdc_debugfs_list,
433 ARRAY_SIZE(tilcdc_debugfs_list),
434 minor->debugfs_root, minor);
435
436 list_for_each_entry(mod, &module_list, list)
437 if (mod->funcs->debugfs_init)
438 mod->funcs->debugfs_init(mod, minor);
439
440 if (ret) {
441 dev_err(dev->dev, "could not install tilcdc_debugfs_list\n");
442 return ret;
443 }
444
445 return ret;
446}
447
448static void tilcdc_debugfs_cleanup(struct drm_minor *minor)
449{
450 struct tilcdc_module *mod;
451 drm_debugfs_remove_files(tilcdc_debugfs_list,
452 ARRAY_SIZE(tilcdc_debugfs_list), minor);
453
454 list_for_each_entry(mod, &module_list, list)
455 if (mod->funcs->debugfs_cleanup)
456 mod->funcs->debugfs_cleanup(mod, minor);
457}
458#endif
459
460static const struct file_operations fops = {
461 .owner = THIS_MODULE,
462 .open = drm_open,
463 .release = drm_release,
464 .unlocked_ioctl = drm_ioctl,
465#ifdef CONFIG_COMPAT
466 .compat_ioctl = drm_compat_ioctl,
467#endif
468 .poll = drm_poll,
469 .read = drm_read,
470 .fasync = drm_fasync,
471 .llseek = no_llseek,
472 .mmap = drm_gem_cma_mmap,
473};
474
475static struct drm_driver tilcdc_driver = {
476 .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET,
477 .load = tilcdc_load,
478 .unload = tilcdc_unload,
479 .preclose = tilcdc_preclose,
480 .lastclose = tilcdc_lastclose,
481 .irq_handler = tilcdc_irq,
482 .irq_preinstall = tilcdc_irq_preinstall,
483 .irq_postinstall = tilcdc_irq_postinstall,
484 .irq_uninstall = tilcdc_irq_uninstall,
485 .get_vblank_counter = drm_vblank_count,
486 .enable_vblank = tilcdc_enable_vblank,
487 .disable_vblank = tilcdc_disable_vblank,
488 .gem_free_object = drm_gem_cma_free_object,
489 .gem_vm_ops = &drm_gem_cma_vm_ops,
490 .dumb_create = drm_gem_cma_dumb_create,
491 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
492 .dumb_destroy = drm_gem_cma_dumb_destroy,
493#ifdef CONFIG_DEBUG_FS
494 .debugfs_init = tilcdc_debugfs_init,
495 .debugfs_cleanup = tilcdc_debugfs_cleanup,
496#endif
497 .fops = &fops,
498 .name = "tilcdc",
499 .desc = "TI LCD Controller DRM",
500 .date = "20121205",
501 .major = 1,
502 .minor = 0,
503};
504
505/*
506 * Power management:
507 */
508
509#ifdef CONFIG_PM_SLEEP
510static int tilcdc_pm_suspend(struct device *dev)
511{
512 struct drm_device *ddev = dev_get_drvdata(dev);
513 struct tilcdc_drm_private *priv = ddev->dev_private;
514 unsigned i, n = 0;
515
516 drm_kms_helper_poll_disable(ddev);
517
518 /* Save register state: */
519 for (i = 0; i < ARRAY_SIZE(registers); i++)
520 if (registers[i].save && (priv->rev >= registers[i].rev))
521 priv->saved_register[n++] = tilcdc_read(ddev, registers[i].reg);
522
523 return 0;
524}
525
526static int tilcdc_pm_resume(struct device *dev)
527{
528 struct drm_device *ddev = dev_get_drvdata(dev);
529 struct tilcdc_drm_private *priv = ddev->dev_private;
530 unsigned i, n = 0;
531
532 /* Restore register state: */
533 for (i = 0; i < ARRAY_SIZE(registers); i++)
534 if (registers[i].save && (priv->rev >= registers[i].rev))
535 tilcdc_write(ddev, registers[i].reg, priv->saved_register[n++]);
536
537 drm_kms_helper_poll_enable(ddev);
538
539 return 0;
540}
541#endif
542
543static const struct dev_pm_ops tilcdc_pm_ops = {
544 SET_SYSTEM_SLEEP_PM_OPS(tilcdc_pm_suspend, tilcdc_pm_resume)
545};
546
547/*
548 * Platform driver:
549 */
550
551static int tilcdc_pdev_probe(struct platform_device *pdev)
552{
553 /* bail out early if no DT data: */
554 if (!pdev->dev.of_node) {
555 dev_err(&pdev->dev, "device-tree data is missing\n");
556 return -ENXIO;
557 }
558
559 return drm_platform_init(&tilcdc_driver, pdev);
560}
561
562static int tilcdc_pdev_remove(struct platform_device *pdev)
563{
564 drm_platform_exit(&tilcdc_driver, pdev);
565
566 return 0;
567}
568
569static struct of_device_id tilcdc_of_match[] = {
570 { .compatible = "ti,am33xx-tilcdc", },
571 { },
572};
573MODULE_DEVICE_TABLE(of, tilcdc_of_match);
574
575static struct platform_driver tilcdc_platform_driver = {
576 .probe = tilcdc_pdev_probe,
577 .remove = tilcdc_pdev_remove,
578 .driver = {
579 .owner = THIS_MODULE,
580 .name = "tilcdc",
581 .pm = &tilcdc_pm_ops,
582 .of_match_table = tilcdc_of_match,
583 },
584};
585
586static int __init tilcdc_drm_init(void)
587{
588 DBG("init");
589 tilcdc_tfp410_init();
590 return platform_driver_register(&tilcdc_platform_driver);
591}
592
593static void __exit tilcdc_drm_fini(void)
594{
595 DBG("fini");
596 tilcdc_tfp410_fini();
597 platform_driver_unregister(&tilcdc_platform_driver);
598}
599
600module_init(tilcdc_drm_init);
601module_exit(tilcdc_drm_fini);
602
603MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
604MODULE_DESCRIPTION("TI LCD Controller DRM Driver");
605MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
new file mode 100644
index 000000000000..8242b5a4307b
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -0,0 +1,150 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __TILCDC_DRV_H__
19#define __TILCDC_DRV_H__
20
21#include <linux/clk.h>
22#include <linux/cpufreq.h>
23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/pm.h>
26#include <linux/pm_runtime.h>
27#include <linux/slab.h>
28#include <linux/of.h>
29#include <linux/of_device.h>
30#include <linux/list.h>
31
32#include <drm/drmP.h>
33#include <drm/drm_crtc_helper.h>
34#include <drm/drm_gem_cma_helper.h>
35#include <drm/drm_fb_cma_helper.h>
36
37struct tilcdc_drm_private {
38 void __iomem *mmio;
39
40 struct clk *disp_clk; /* display dpll */
41 struct clk *clk; /* functional clock */
42 int rev; /* IP revision */
43
44 /* don't attempt resolutions w/ higher W * H * Hz: */
45 uint32_t max_bandwidth;
46
47 /* register contents saved across suspend/resume: */
48 u32 saved_register[12];
49
50#ifdef CONFIG_CPU_FREQ
51 struct notifier_block freq_transition;
52 unsigned int lcd_fck_rate;
53#endif
54
55 struct workqueue_struct *wq;
56
57 struct drm_fbdev_cma *fbdev;
58
59 struct drm_crtc *crtc;
60
61 unsigned int num_encoders;
62 struct drm_encoder *encoders[8];
63
64 unsigned int num_connectors;
65 struct drm_connector *connectors[8];
66};
67
68/* Sub-module for display. Since we don't know at compile time what panels
69 * or display adapter(s) might be present (for ex, off chip dvi/tfp410,
70 * hdmi encoder, various lcd panels), the connector/encoder(s) are split into
71 * separate drivers. If they are probed and found to be present, they
72 * register themselves with tilcdc_register_module().
73 */
74struct tilcdc_module;
75
76struct tilcdc_module_ops {
77 /* create appropriate encoders/connectors: */
78 int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev);
79 void (*destroy)(struct tilcdc_module *mod);
80#ifdef CONFIG_DEBUG_FS
81 /* create debugfs nodes (can be NULL): */
82 int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor);
83 /* cleanup debugfs nodes (can be NULL): */
84 void (*debugfs_cleanup)(struct tilcdc_module *mod, struct drm_minor *minor);
85#endif
86};
87
88struct tilcdc_module {
89 const char *name;
90 struct list_head list;
91 const struct tilcdc_module_ops *funcs;
92};
93
94void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
95 const struct tilcdc_module_ops *funcs);
96void tilcdc_module_cleanup(struct tilcdc_module *mod);
97
98
99/* Panel config that needs to be set in the crtc, but is not coming from
100 * the mode timings. The display module is expected to call
101 * tilcdc_crtc_set_panel_info() to set this during modeset.
102 */
103struct tilcdc_panel_info {
104
105 /* AC Bias Pin Frequency */
106 uint32_t ac_bias;
107
108 /* AC Bias Pin Transitions per Interrupt */
109 uint32_t ac_bias_intrpt;
110
111 /* DMA burst size */
112 uint32_t dma_burst_sz;
113
114 /* Bits per pixel */
115 uint32_t bpp;
116
117 /* FIFO DMA Request Delay */
118 uint32_t fdd;
119
120 /* TFT Alternative Signal Mapping (Only for active) */
121 bool tft_alt_mode;
122
123 /* Invert pixel clock */
124 bool invert_pxl_clk;
125
126 /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */
127 uint32_t sync_edge;
128
129 /* Horizontal and Vertical Sync: Control: 0=ignore */
130 uint32_t sync_ctrl;
131
132 /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */
133 uint32_t raster_order;
134
135 /* DMA FIFO threshold */
136 uint32_t fifo_th;
137};
138
139#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
140
141struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev);
142void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
143irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
144void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
145void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
146 const struct tilcdc_panel_info *info);
147int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
148int tilcdc_crtc_max_width(struct drm_crtc *crtc);
149
150#endif /* __TILCDC_DRV_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
new file mode 100644
index 000000000000..17fd1b45428a
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h
@@ -0,0 +1,154 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __TILCDC_REGS_H__
19#define __TILCDC_REGS_H__
20
21/* LCDC register definitions, based on da8xx-fb */
22
23#include <linux/bitops.h>
24
25#include "tilcdc_drv.h"
26
27/* LCDC Status Register */
28#define LCDC_END_OF_FRAME1 BIT(9)
29#define LCDC_END_OF_FRAME0 BIT(8)
30#define LCDC_PL_LOAD_DONE BIT(6)
31#define LCDC_FIFO_UNDERFLOW BIT(5)
32#define LCDC_SYNC_LOST BIT(2)
33#define LCDC_FRAME_DONE BIT(0)
34
35/* LCDC DMA Control Register */
36#define LCDC_DMA_BURST_SIZE(x) ((x) << 4)
37#define LCDC_DMA_BURST_1 0x0
38#define LCDC_DMA_BURST_2 0x1
39#define LCDC_DMA_BURST_4 0x2
40#define LCDC_DMA_BURST_8 0x3
41#define LCDC_DMA_BURST_16 0x4
42#define LCDC_V1_END_OF_FRAME_INT_ENA BIT(2)
43#define LCDC_V2_END_OF_FRAME0_INT_ENA BIT(8)
44#define LCDC_V2_END_OF_FRAME1_INT_ENA BIT(9)
45#define LCDC_DUAL_FRAME_BUFFER_ENABLE BIT(0)
46
47/* LCDC Control Register */
48#define LCDC_CLK_DIVISOR(x) ((x) << 8)
49#define LCDC_RASTER_MODE 0x01
50
51/* LCDC Raster Control Register */
52#define LCDC_PALETTE_LOAD_MODE(x) ((x) << 20)
53#define PALETTE_AND_DATA 0x00
54#define PALETTE_ONLY 0x01
55#define DATA_ONLY 0x02
56
57#define LCDC_MONO_8BIT_MODE BIT(9)
58#define LCDC_RASTER_ORDER BIT(8)
59#define LCDC_TFT_MODE BIT(7)
60#define LCDC_V1_UNDERFLOW_INT_ENA BIT(6)
61#define LCDC_V2_UNDERFLOW_INT_ENA BIT(5)
62#define LCDC_V1_PL_INT_ENA BIT(4)
63#define LCDC_V2_PL_INT_ENA BIT(6)
64#define LCDC_MONOCHROME_MODE BIT(1)
65#define LCDC_RASTER_ENABLE BIT(0)
66#define LCDC_TFT_ALT_ENABLE BIT(23)
67#define LCDC_STN_565_ENABLE BIT(24)
68#define LCDC_V2_DMA_CLK_EN BIT(2)
69#define LCDC_V2_LIDD_CLK_EN BIT(1)
70#define LCDC_V2_CORE_CLK_EN BIT(0)
71#define LCDC_V2_LPP_B10 26
72#define LCDC_V2_TFT_24BPP_MODE BIT(25)
73#define LCDC_V2_TFT_24BPP_UNPACK BIT(26)
74
75/* LCDC Raster Timing 2 Register */
76#define LCDC_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
77#define LCDC_AC_BIAS_FREQUENCY(x) ((x) << 8)
78#define LCDC_SYNC_CTRL BIT(25)
79#define LCDC_SYNC_EDGE BIT(24)
80#define LCDC_INVERT_PIXEL_CLOCK BIT(22)
81#define LCDC_INVERT_HSYNC BIT(21)
82#define LCDC_INVERT_VSYNC BIT(20)
83
84/* LCDC Block */
85#define LCDC_PID_REG 0x0
86#define LCDC_CTRL_REG 0x4
87#define LCDC_STAT_REG 0x8
88#define LCDC_RASTER_CTRL_REG 0x28
89#define LCDC_RASTER_TIMING_0_REG 0x2c
90#define LCDC_RASTER_TIMING_1_REG 0x30
91#define LCDC_RASTER_TIMING_2_REG 0x34
92#define LCDC_DMA_CTRL_REG 0x40
93#define LCDC_DMA_FB_BASE_ADDR_0_REG 0x44
94#define LCDC_DMA_FB_CEILING_ADDR_0_REG 0x48
95#define LCDC_DMA_FB_BASE_ADDR_1_REG 0x4c
96#define LCDC_DMA_FB_CEILING_ADDR_1_REG 0x50
97
98/* Interrupt Registers available only in Version 2 */
99#define LCDC_RAW_STAT_REG 0x58
100#define LCDC_MASKED_STAT_REG 0x5c
101#define LCDC_INT_ENABLE_SET_REG 0x60
102#define LCDC_INT_ENABLE_CLR_REG 0x64
103#define LCDC_END_OF_INT_IND_REG 0x68
104
105/* Clock registers available only on Version 2 */
106#define LCDC_CLK_ENABLE_REG 0x6c
107#define LCDC_CLK_RESET_REG 0x70
108#define LCDC_CLK_MAIN_RESET BIT(3)
109
110
111/*
112 * Helpers:
113 */
114
115static inline void tilcdc_write(struct drm_device *dev, u32 reg, u32 data)
116{
117 struct tilcdc_drm_private *priv = dev->dev_private;
118 iowrite32(data, priv->mmio + reg);
119}
120
121static inline u32 tilcdc_read(struct drm_device *dev, u32 reg)
122{
123 struct tilcdc_drm_private *priv = dev->dev_private;
124 return ioread32(priv->mmio + reg);
125}
126
127static inline void tilcdc_set(struct drm_device *dev, u32 reg, u32 mask)
128{
129 tilcdc_write(dev, reg, tilcdc_read(dev, reg) | mask);
130}
131
132static inline void tilcdc_clear(struct drm_device *dev, u32 reg, u32 mask)
133{
134 tilcdc_write(dev, reg, tilcdc_read(dev, reg) & ~mask);
135}
136
137/* the register to read/clear irqstatus differs between v1 and v2 of the IP */
138static inline u32 tilcdc_irqstatus_reg(struct drm_device *dev)
139{
140 struct tilcdc_drm_private *priv = dev->dev_private;
141 return (priv->rev == 2) ? LCDC_MASKED_STAT_REG : LCDC_STAT_REG;
142}
143
144static inline u32 tilcdc_read_irqstatus(struct drm_device *dev)
145{
146 return tilcdc_read(dev, tilcdc_irqstatus_reg(dev));
147}
148
149static inline void tilcdc_clear_irqstatus(struct drm_device *dev, u32 mask)
150{
151 tilcdc_write(dev, tilcdc_irqstatus_reg(dev), mask);
152}
153
154#endif /* __TILCDC_REGS_H__ */
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
new file mode 100644
index 000000000000..58d487ba2414
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
@@ -0,0 +1,419 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/i2c.h>
19#include <linux/of_i2c.h>
20#include <linux/gpio.h>
21#include <linux/of_gpio.h>
22#include <linux/pinctrl/pinmux.h>
23#include <linux/pinctrl/consumer.h>
24
25#include "tilcdc_drv.h"
26
27struct tfp410_module {
28 struct tilcdc_module base;
29 struct i2c_adapter *i2c;
30 int gpio;
31};
32#define to_tfp410_module(x) container_of(x, struct tfp410_module, base)
33
34
35static const struct tilcdc_panel_info dvi_info = {
36 .ac_bias = 255,
37 .ac_bias_intrpt = 0,
38 .dma_burst_sz = 16,
39 .bpp = 16,
40 .fdd = 0x80,
41 .tft_alt_mode = 0,
42 .sync_edge = 0,
43 .sync_ctrl = 1,
44 .raster_order = 0,
45};
46
47/*
48 * Encoder:
49 */
50
51struct tfp410_encoder {
52 struct drm_encoder base;
53 struct tfp410_module *mod;
54 int dpms;
55};
56#define to_tfp410_encoder(x) container_of(x, struct tfp410_encoder, base)
57
58
59static void tfp410_encoder_destroy(struct drm_encoder *encoder)
60{
61 struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
62 drm_encoder_cleanup(encoder);
63 kfree(tfp410_encoder);
64}
65
66static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode)
67{
68 struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder);
69
70 if (tfp410_encoder->dpms == mode)
71 return;
72
73 if (mode == DRM_MODE_DPMS_ON) {
74 DBG("Power on");
75 gpio_direction_output(tfp410_encoder->mod->gpio, 1);
76 } else {
77 DBG("Power off");
78 gpio_direction_output(tfp410_encoder->mod->gpio, 0);
79 }
80
81 tfp410_encoder->dpms = mode;
82}
83
84static bool tfp410_encoder_mode_fixup(struct drm_encoder *encoder,
85 const struct drm_display_mode *mode,
86 struct drm_display_mode *adjusted_mode)
87{
88 /* nothing needed */
89 return true;
90}
91
92static void tfp410_encoder_prepare(struct drm_encoder *encoder)
93{
94 tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
95 tilcdc_crtc_set_panel_info(encoder->crtc, &dvi_info);
96}
97
98static void tfp410_encoder_commit(struct drm_encoder *encoder)
99{
100 tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
101}
102
103static void tfp410_encoder_mode_set(struct drm_encoder *encoder,
104 struct drm_display_mode *mode,
105 struct drm_display_mode *adjusted_mode)
106{
107 /* nothing needed */
108}
109
110static const struct drm_encoder_funcs tfp410_encoder_funcs = {
111 .destroy = tfp410_encoder_destroy,
112};
113
114static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = {
115 .dpms = tfp410_encoder_dpms,
116 .mode_fixup = tfp410_encoder_mode_fixup,
117 .prepare = tfp410_encoder_prepare,
118 .commit = tfp410_encoder_commit,
119 .mode_set = tfp410_encoder_mode_set,
120};
121
122static struct drm_encoder *tfp410_encoder_create(struct drm_device *dev,
123 struct tfp410_module *mod)
124{
125 struct tfp410_encoder *tfp410_encoder;
126 struct drm_encoder *encoder;
127 int ret;
128
129 tfp410_encoder = kzalloc(sizeof(*tfp410_encoder), GFP_KERNEL);
130 if (!tfp410_encoder) {
131 dev_err(dev->dev, "allocation failed\n");
132 return NULL;
133 }
134
135 tfp410_encoder->dpms = DRM_MODE_DPMS_OFF;
136 tfp410_encoder->mod = mod;
137
138 encoder = &tfp410_encoder->base;
139 encoder->possible_crtcs = 1;
140
141 ret = drm_encoder_init(dev, encoder, &tfp410_encoder_funcs,
142 DRM_MODE_ENCODER_TMDS);
143 if (ret < 0)
144 goto fail;
145
146 drm_encoder_helper_add(encoder, &tfp410_encoder_helper_funcs);
147
148 return encoder;
149
150fail:
151 tfp410_encoder_destroy(encoder);
152 return NULL;
153}
154
155/*
156 * Connector:
157 */
158
159struct tfp410_connector {
160 struct drm_connector base;
161
162 struct drm_encoder *encoder; /* our connected encoder */
163 struct tfp410_module *mod;
164};
165#define to_tfp410_connector(x) container_of(x, struct tfp410_connector, base)
166
167
168static void tfp410_connector_destroy(struct drm_connector *connector)
169{
170 struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
171 drm_connector_cleanup(connector);
172 kfree(tfp410_connector);
173}
174
175static enum drm_connector_status tfp410_connector_detect(
176 struct drm_connector *connector,
177 bool force)
178{
179 struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
180
181 if (drm_probe_ddc(tfp410_connector->mod->i2c))
182 return connector_status_connected;
183
184 return connector_status_unknown;
185}
186
187static int tfp410_connector_get_modes(struct drm_connector *connector)
188{
189 struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
190 struct edid *edid;
191 int ret = 0;
192
193 edid = drm_get_edid(connector, tfp410_connector->mod->i2c);
194
195 drm_mode_connector_update_edid_property(connector, edid);
196
197 if (edid) {
198 ret = drm_add_edid_modes(connector, edid);
199 kfree(edid);
200 }
201
202 return ret;
203}
204
205static int tfp410_connector_mode_valid(struct drm_connector *connector,
206 struct drm_display_mode *mode)
207{
208 struct tilcdc_drm_private *priv = connector->dev->dev_private;
209 /* our only constraints are what the crtc can generate: */
210 return tilcdc_crtc_mode_valid(priv->crtc, mode);
211}
212
213static struct drm_encoder *tfp410_connector_best_encoder(
214 struct drm_connector *connector)
215{
216 struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector);
217 return tfp410_connector->encoder;
218}
219
220static const struct drm_connector_funcs tfp410_connector_funcs = {
221 .destroy = tfp410_connector_destroy,
222 .dpms = drm_helper_connector_dpms,
223 .detect = tfp410_connector_detect,
224 .fill_modes = drm_helper_probe_single_connector_modes,
225};
226
227static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = {
228 .get_modes = tfp410_connector_get_modes,
229 .mode_valid = tfp410_connector_mode_valid,
230 .best_encoder = tfp410_connector_best_encoder,
231};
232
233static struct drm_connector *tfp410_connector_create(struct drm_device *dev,
234 struct tfp410_module *mod, struct drm_encoder *encoder)
235{
236 struct tfp410_connector *tfp410_connector;
237 struct drm_connector *connector;
238 int ret;
239
240 tfp410_connector = kzalloc(sizeof(*tfp410_connector), GFP_KERNEL);
241 if (!tfp410_connector) {
242 dev_err(dev->dev, "allocation failed\n");
243 return NULL;
244 }
245
246 tfp410_connector->encoder = encoder;
247 tfp410_connector->mod = mod;
248
249 connector = &tfp410_connector->base;
250
251 drm_connector_init(dev, connector, &tfp410_connector_funcs,
252 DRM_MODE_CONNECTOR_DVID);
253 drm_connector_helper_add(connector, &tfp410_connector_helper_funcs);
254
255 connector->polled = DRM_CONNECTOR_POLL_CONNECT |
256 DRM_CONNECTOR_POLL_DISCONNECT;
257
258 connector->interlace_allowed = 0;
259 connector->doublescan_allowed = 0;
260
261 ret = drm_mode_connector_attach_encoder(connector, encoder);
262 if (ret)
263 goto fail;
264
265 drm_sysfs_connector_add(connector);
266
267 return connector;
268
269fail:
270 tfp410_connector_destroy(connector);
271 return NULL;
272}
273
274/*
275 * Module:
276 */
277
278static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
279{
280 struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
281 struct tilcdc_drm_private *priv = dev->dev_private;
282 struct drm_encoder *encoder;
283 struct drm_connector *connector;
284
285 encoder = tfp410_encoder_create(dev, tfp410_mod);
286 if (!encoder)
287 return -ENOMEM;
288
289 connector = tfp410_connector_create(dev, tfp410_mod, encoder);
290 if (!connector)
291 return -ENOMEM;
292
293 priv->encoders[priv->num_encoders++] = encoder;
294 priv->connectors[priv->num_connectors++] = connector;
295
296 return 0;
297}
298
299static void tfp410_destroy(struct tilcdc_module *mod)
300{
301 struct tfp410_module *tfp410_mod = to_tfp410_module(mod);
302
303 if (tfp410_mod->i2c)
304 i2c_put_adapter(tfp410_mod->i2c);
305
306 if (!IS_ERR_VALUE(tfp410_mod->gpio))
307 gpio_free(tfp410_mod->gpio);
308
309 tilcdc_module_cleanup(mod);
310 kfree(tfp410_mod);
311}
312
313static const struct tilcdc_module_ops tfp410_module_ops = {
314 .modeset_init = tfp410_modeset_init,
315 .destroy = tfp410_destroy,
316};
317
318/*
319 * Device:
320 */
321
322static struct of_device_id tfp410_of_match[];
323
324static int tfp410_probe(struct platform_device *pdev)
325{
326 struct device_node *node = pdev->dev.of_node;
327 struct device_node *i2c_node;
328 struct tfp410_module *tfp410_mod;
329 struct tilcdc_module *mod;
330 struct pinctrl *pinctrl;
331 uint32_t i2c_phandle;
332 int ret = -EINVAL;
333
334 /* bail out early if no DT data: */
335 if (!node) {
336 dev_err(&pdev->dev, "device-tree data is missing\n");
337 return -ENXIO;
338 }
339
340 tfp410_mod = kzalloc(sizeof(*tfp410_mod), GFP_KERNEL);
341 if (!tfp410_mod)
342 return -ENOMEM;
343
344 mod = &tfp410_mod->base;
345
346 tilcdc_module_init(mod, "tfp410", &tfp410_module_ops);
347
348 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
349 if (IS_ERR(pinctrl))
350 dev_warn(&pdev->dev, "pins are not configured\n");
351
352 if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
353 dev_err(&pdev->dev, "could not get i2c bus phandle\n");
354 goto fail;
355 }
356
357 i2c_node = of_find_node_by_phandle(i2c_phandle);
358 if (!i2c_node) {
359 dev_err(&pdev->dev, "could not get i2c bus node\n");
360 goto fail;
361 }
362
363 tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
364 if (!tfp410_mod->i2c) {
365 dev_err(&pdev->dev, "could not get i2c\n");
366 goto fail;
367 }
368
369 of_node_put(i2c_node);
370
371 tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio",
372 0, NULL);
373 if (IS_ERR_VALUE(tfp410_mod->gpio)) {
374 dev_warn(&pdev->dev, "No power down GPIO\n");
375 } else {
376 ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
377 if (ret) {
378 dev_err(&pdev->dev, "could not get DVI_PDn gpio\n");
379 goto fail;
380 }
381 }
382
383 return 0;
384
385fail:
386 tfp410_destroy(mod);
387 return ret;
388}
389
390static int tfp410_remove(struct platform_device *pdev)
391{
392 return 0;
393}
394
395static struct of_device_id tfp410_of_match[] = {
396 { .compatible = "ti,tilcdc,tfp410", },
397 { },
398};
399MODULE_DEVICE_TABLE(of, tfp410_of_match);
400
401struct platform_driver tfp410_driver = {
402 .probe = tfp410_probe,
403 .remove = tfp410_remove,
404 .driver = {
405 .owner = THIS_MODULE,
406 .name = "tfp410",
407 .of_match_table = tfp410_of_match,
408 },
409};
410
411int __init tilcdc_tfp410_init(void)
412{
413 return platform_driver_register(&tfp410_driver);
414}
415
416void __exit tilcdc_tfp410_fini(void)
417{
418 platform_driver_unregister(&tfp410_driver);
419}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
new file mode 100644
index 000000000000..5b800f1f6aa5
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __TILCDC_TFP410_H__
19#define __TILCDC_TFP410_H__
20
21/* sub-module for tfp410 dvi adaptor */
22
23int tilcdc_tfp410_init(void);
24void tilcdc_tfp410_fini(void);
25
26#endif /* __TILCDC_TFP410_H__ */