aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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__ */