aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tilcdc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
-rw-r--r--drivers/gpu/drm/tilcdc/Kconfig13
-rw-r--r--drivers/gpu/drm/tilcdc/Makefile10
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_crtc.c602
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c611
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h150
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c436
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.h26
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_regs.h154
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_slave.c376
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_slave.h26
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.c419
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_tfp410.h26
12 files changed, 2849 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
new file mode 100644
index 000000000000..d24d04013476
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/Kconfig
@@ -0,0 +1,13 @@
1config DRM_TILCDC
2 tristate "DRM Support for TI LCDC Display Controller"
3 depends on DRM && OF && ARM
4 select DRM_KMS_HELPER
5 select DRM_KMS_CMA_HELPER
6 select DRM_GEM_CMA_HELPER
7 select OF_VIDEOMODE
8 select OF_DISPLAY_TIMING
9 select BACKLIGHT_CLASS_DEVICE
10 help
11 Choose this option if you have an TI SoC with LCDC display
12 controller, for example AM33xx in beagle-bone, DA8xx, or
13 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..deda656b10e7
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/Makefile
@@ -0,0 +1,10 @@
1ccflags-y := -Iinclude/drm -Werror
2
3tilcdc-y := \
4 tilcdc_crtc.o \
5 tilcdc_tfp410.o \
6 tilcdc_slave.o \
7 tilcdc_panel.o \
8 tilcdc_drv.o
9
10obj-$(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..c5b592dc1970
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -0,0 +1,611 @@
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#include "tilcdc_slave.h"
24#include "tilcdc_panel.h"
25
26#include "drm_fb_helper.h"
27
28static LIST_HEAD(module_list);
29
30void tilcdc_module_init(struct tilcdc_module *mod, const char *name,
31 const struct tilcdc_module_ops *funcs)
32{
33 mod->name = name;
34 mod->funcs = funcs;
35 INIT_LIST_HEAD(&mod->list);
36 list_add(&mod->list, &module_list);
37}
38
39void tilcdc_module_cleanup(struct tilcdc_module *mod)
40{
41 list_del(&mod->list);
42}
43
44static struct of_device_id tilcdc_of_match[];
45
46static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,
47 struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
48{
49 return drm_fb_cma_create(dev, file_priv, mode_cmd);
50}
51
52static void tilcdc_fb_output_poll_changed(struct drm_device *dev)
53{
54 struct tilcdc_drm_private *priv = dev->dev_private;
55 if (priv->fbdev)
56 drm_fbdev_cma_hotplug_event(priv->fbdev);
57}
58
59static const struct drm_mode_config_funcs mode_config_funcs = {
60 .fb_create = tilcdc_fb_create,
61 .output_poll_changed = tilcdc_fb_output_poll_changed,
62};
63
64static int modeset_init(struct drm_device *dev)
65{
66 struct tilcdc_drm_private *priv = dev->dev_private;
67 struct tilcdc_module *mod;
68
69 drm_mode_config_init(dev);
70
71 priv->crtc = tilcdc_crtc_create(dev);
72
73 list_for_each_entry(mod, &module_list, list) {
74 DBG("loading module: %s", mod->name);
75 mod->funcs->modeset_init(mod, dev);
76 }
77
78 if ((priv->num_encoders = 0) || (priv->num_connectors == 0)) {
79 /* oh nos! */
80 dev_err(dev->dev, "no encoders/connectors found\n");
81 return -ENXIO;
82 }
83
84 dev->mode_config.min_width = 0;
85 dev->mode_config.min_height = 0;
86 dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
87 dev->mode_config.max_height = 2048;
88 dev->mode_config.funcs = &mode_config_funcs;
89
90 return 0;
91}
92
93#ifdef CONFIG_CPU_FREQ
94static int cpufreq_transition(struct notifier_block *nb,
95 unsigned long val, void *data)
96{
97 struct tilcdc_drm_private *priv = container_of(nb,
98 struct tilcdc_drm_private, freq_transition);
99 if (val == CPUFREQ_POSTCHANGE) {
100 if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) {
101 priv->lcd_fck_rate = clk_get_rate(priv->clk);
102 tilcdc_crtc_update_clk(priv->crtc);
103 }
104 }
105
106 return 0;
107}
108#endif
109
110/*
111 * DRM operations:
112 */
113
114static int tilcdc_unload(struct drm_device *dev)
115{
116 struct tilcdc_drm_private *priv = dev->dev_private;
117 struct tilcdc_module *mod, *cur;
118
119 drm_kms_helper_poll_fini(dev);
120 drm_mode_config_cleanup(dev);
121 drm_vblank_cleanup(dev);
122
123 pm_runtime_get_sync(dev->dev);
124 drm_irq_uninstall(dev);
125 pm_runtime_put_sync(dev->dev);
126
127#ifdef CONFIG_CPU_FREQ
128 cpufreq_unregister_notifier(&priv->freq_transition,
129 CPUFREQ_TRANSITION_NOTIFIER);
130#endif
131
132 if (priv->clk)
133 clk_put(priv->clk);
134
135 if (priv->mmio)
136 iounmap(priv->mmio);
137
138 flush_workqueue(priv->wq);
139 destroy_workqueue(priv->wq);
140
141 dev->dev_private = NULL;
142
143 pm_runtime_disable(dev->dev);
144
145 list_for_each_entry_safe(mod, cur, &module_list, list) {
146 DBG("destroying module: %s", mod->name);
147 mod->funcs->destroy(mod);
148 }
149
150 kfree(priv);
151
152 return 0;
153}
154
155static int tilcdc_load(struct drm_device *dev, unsigned long flags)
156{
157 struct platform_device *pdev = dev->platformdev;
158 struct device_node *node = pdev->dev.of_node;
159 struct tilcdc_drm_private *priv;
160 struct resource *res;
161 int ret;
162
163 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
164 if (!priv) {
165 dev_err(dev->dev, "failed to allocate private data\n");
166 return -ENOMEM;
167 }
168
169 dev->dev_private = priv;
170
171 priv->wq = alloc_ordered_workqueue("tilcdc", 0);
172
173 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
174 if (!res) {
175 dev_err(dev->dev, "failed to get memory resource\n");
176 ret = -EINVAL;
177 goto fail;
178 }
179
180 priv->mmio = ioremap_nocache(res->start, resource_size(res));
181 if (!priv->mmio) {
182 dev_err(dev->dev, "failed to ioremap\n");
183 ret = -ENOMEM;
184 goto fail;
185 }
186
187 priv->clk = clk_get(dev->dev, "fck");
188 if (IS_ERR(priv->clk)) {
189 dev_err(dev->dev, "failed to get functional clock\n");
190 ret = -ENODEV;
191 goto fail;
192 }
193
194 priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck");
195 if (IS_ERR(priv->clk)) {
196 dev_err(dev->dev, "failed to get display clock\n");
197 ret = -ENODEV;
198 goto fail;
199 }
200
201#ifdef CONFIG_CPU_FREQ
202 priv->lcd_fck_rate = clk_get_rate(priv->clk);
203 priv->freq_transition.notifier_call = cpufreq_transition;
204 ret = cpufreq_register_notifier(&priv->freq_transition,
205 CPUFREQ_TRANSITION_NOTIFIER);
206 if (ret) {
207 dev_err(dev->dev, "failed to register cpufreq notifier\n");
208 goto fail;
209 }
210#endif
211
212 if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth))
213 priv->max_bandwidth = 1280 * 1024 * 60;
214
215 pm_runtime_enable(dev->dev);
216
217 /* Determine LCD IP Version */
218 pm_runtime_get_sync(dev->dev);
219 switch (tilcdc_read(dev, LCDC_PID_REG)) {
220 case 0x4c100102:
221 priv->rev = 1;
222 break;
223 case 0x4f200800:
224 case 0x4f201000:
225 priv->rev = 2;
226 break;
227 default:
228 dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, "
229 "defaulting to LCD revision 1\n",
230 tilcdc_read(dev, LCDC_PID_REG));
231 priv->rev = 1;
232 break;
233 }
234
235 pm_runtime_put_sync(dev->dev);
236
237 ret = modeset_init(dev);
238 if (ret < 0) {
239 dev_err(dev->dev, "failed to initialize mode setting\n");
240 goto fail;
241 }
242
243 ret = drm_vblank_init(dev, 1);
244 if (ret < 0) {
245 dev_err(dev->dev, "failed to initialize vblank\n");
246 goto fail;
247 }
248
249 pm_runtime_get_sync(dev->dev);
250 ret = drm_irq_install(dev);
251 pm_runtime_put_sync(dev->dev);
252 if (ret < 0) {
253 dev_err(dev->dev, "failed to install IRQ handler\n");
254 goto fail;
255 }
256
257 platform_set_drvdata(pdev, dev);
258
259 priv->fbdev = drm_fbdev_cma_init(dev, 16,
260 dev->mode_config.num_crtc,
261 dev->mode_config.num_connector);
262
263 drm_kms_helper_poll_init(dev);
264
265 return 0;
266
267fail:
268 tilcdc_unload(dev);
269 return ret;
270}
271
272static void tilcdc_preclose(struct drm_device *dev, struct drm_file *file)
273{
274 struct tilcdc_drm_private *priv = dev->dev_private;
275
276 tilcdc_crtc_cancel_page_flip(priv->crtc, file);
277}
278
279static void tilcdc_lastclose(struct drm_device *dev)
280{
281 struct tilcdc_drm_private *priv = dev->dev_private;
282 drm_fbdev_cma_restore_mode(priv->fbdev);
283}
284
285static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS)
286{
287 struct drm_device *dev = arg;
288 struct tilcdc_drm_private *priv = dev->dev_private;
289 return tilcdc_crtc_irq(priv->crtc);
290}
291
292static void tilcdc_irq_preinstall(struct drm_device *dev)
293{
294 tilcdc_clear_irqstatus(dev, 0xffffffff);
295}
296
297static int tilcdc_irq_postinstall(struct drm_device *dev)
298{
299 struct tilcdc_drm_private *priv = dev->dev_private;
300
301 /* enable FIFO underflow irq: */
302 if (priv->rev == 1) {
303 tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_UNDERFLOW_INT_ENA);
304 } else {
305 tilcdc_set(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_UNDERFLOW_INT_ENA);
306 }
307
308 return 0;
309}
310
311static void tilcdc_irq_uninstall(struct drm_device *dev)
312{
313 struct tilcdc_drm_private *priv = dev->dev_private;
314
315 /* disable irqs that we might have enabled: */
316 if (priv->rev == 1) {
317 tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
318 LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
319 tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA);
320 } else {
321 tilcdc_clear(dev, LCDC_INT_ENABLE_SET_REG,
322 LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA |
323 LCDC_V2_END_OF_FRAME0_INT_ENA | LCDC_V2_END_OF_FRAME1_INT_ENA |
324 LCDC_FRAME_DONE);
325 }
326
327}
328
329static void enable_vblank(struct drm_device *dev, bool enable)
330{
331 struct tilcdc_drm_private *priv = dev->dev_private;
332 u32 reg, mask;
333
334 if (priv->rev == 1) {
335 reg = LCDC_DMA_CTRL_REG;
336 mask = LCDC_V1_END_OF_FRAME_INT_ENA;
337 } else {
338 reg = LCDC_INT_ENABLE_SET_REG;
339 mask = LCDC_V2_END_OF_FRAME0_INT_ENA |
340 LCDC_V2_END_OF_FRAME1_INT_ENA | LCDC_FRAME_DONE;
341 }
342
343 if (enable)
344 tilcdc_set(dev, reg, mask);
345 else
346 tilcdc_clear(dev, reg, mask);
347}
348
349static int tilcdc_enable_vblank(struct drm_device *dev, int crtc)
350{
351 enable_vblank(dev, true);
352 return 0;
353}
354
355static void tilcdc_disable_vblank(struct drm_device *dev, int crtc)
356{
357 enable_vblank(dev, false);
358}
359
360#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_PM_SLEEP)
361static const struct {
362 const char *name;
363 uint8_t rev;
364 uint8_t save;
365 uint32_t reg;
366} registers[] = {
367#define REG(rev, save, reg) { #reg, rev, save, reg }
368 /* exists in revision 1: */
369 REG(1, false, LCDC_PID_REG),
370 REG(1, true, LCDC_CTRL_REG),
371 REG(1, false, LCDC_STAT_REG),
372 REG(1, true, LCDC_RASTER_CTRL_REG),
373 REG(1, true, LCDC_RASTER_TIMING_0_REG),
374 REG(1, true, LCDC_RASTER_TIMING_1_REG),
375 REG(1, true, LCDC_RASTER_TIMING_2_REG),
376 REG(1, true, LCDC_DMA_CTRL_REG),
377 REG(1, true, LCDC_DMA_FB_BASE_ADDR_0_REG),
378 REG(1, true, LCDC_DMA_FB_CEILING_ADDR_0_REG),
379 REG(1, true, LCDC_DMA_FB_BASE_ADDR_1_REG),
380 REG(1, true, LCDC_DMA_FB_CEILING_ADDR_1_REG),
381 /* new in revision 2: */
382 REG(2, false, LCDC_RAW_STAT_REG),
383 REG(2, false, LCDC_MASKED_STAT_REG),
384 REG(2, false, LCDC_INT_ENABLE_SET_REG),
385 REG(2, false, LCDC_INT_ENABLE_CLR_REG),
386 REG(2, false, LCDC_END_OF_INT_IND_REG),
387 REG(2, true, LCDC_CLK_ENABLE_REG),
388 REG(2, true, LCDC_INT_ENABLE_SET_REG),
389#undef REG
390};
391#endif
392
393#ifdef CONFIG_DEBUG_FS
394static int tilcdc_regs_show(struct seq_file *m, void *arg)
395{
396 struct drm_info_node *node = (struct drm_info_node *) m->private;
397 struct drm_device *dev = node->minor->dev;
398 struct tilcdc_drm_private *priv = dev->dev_private;
399 unsigned i;
400
401 pm_runtime_get_sync(dev->dev);
402
403 seq_printf(m, "revision: %d\n", priv->rev);
404
405 for (i = 0; i < ARRAY_SIZE(registers); i++)
406 if (priv->rev >= registers[i].rev)
407 seq_printf(m, "%s:\t %08x\n", registers[i].name,
408 tilcdc_read(dev, registers[i].reg));
409
410 pm_runtime_put_sync(dev->dev);
411
412 return 0;
413}
414
415static int tilcdc_mm_show(struct seq_file *m, void *arg)
416{
417 struct drm_info_node *node = (struct drm_info_node *) m->private;
418 struct drm_device *dev = node->minor->dev;
419 return drm_mm_dump_table(m, dev->mm_private);
420}
421
422static struct drm_info_list tilcdc_debugfs_list[] = {
423 { "regs", tilcdc_regs_show, 0 },
424 { "mm", tilcdc_mm_show, 0 },
425 { "fb", drm_fb_cma_debugfs_show, 0 },
426};
427
428static int tilcdc_debugfs_init(struct drm_minor *minor)
429{
430 struct drm_device *dev = minor->dev;
431 struct tilcdc_module *mod;
432 int ret;
433
434 ret = drm_debugfs_create_files(tilcdc_debugfs_list,
435 ARRAY_SIZE(tilcdc_debugfs_list),
436 minor->debugfs_root, minor);
437
438 list_for_each_entry(mod, &module_list, list)
439 if (mod->funcs->debugfs_init)
440 mod->funcs->debugfs_init(mod, minor);
441
442 if (ret) {
443 dev_err(dev->dev, "could not install tilcdc_debugfs_list\n");
444 return ret;
445 }
446
447 return ret;
448}
449
450static void tilcdc_debugfs_cleanup(struct drm_minor *minor)
451{
452 struct tilcdc_module *mod;
453 drm_debugfs_remove_files(tilcdc_debugfs_list,
454 ARRAY_SIZE(tilcdc_debugfs_list), minor);
455
456 list_for_each_entry(mod, &module_list, list)
457 if (mod->funcs->debugfs_cleanup)
458 mod->funcs->debugfs_cleanup(mod, minor);
459}
460#endif
461
462static const struct file_operations fops = {
463 .owner = THIS_MODULE,
464 .open = drm_open,
465 .release = drm_release,
466 .unlocked_ioctl = drm_ioctl,
467#ifdef CONFIG_COMPAT
468 .compat_ioctl = drm_compat_ioctl,
469#endif
470 .poll = drm_poll,
471 .read = drm_read,
472 .fasync = drm_fasync,
473 .llseek = no_llseek,
474 .mmap = drm_gem_cma_mmap,
475};
476
477static struct drm_driver tilcdc_driver = {
478 .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET,
479 .load = tilcdc_load,
480 .unload = tilcdc_unload,
481 .preclose = tilcdc_preclose,
482 .lastclose = tilcdc_lastclose,
483 .irq_handler = tilcdc_irq,
484 .irq_preinstall = tilcdc_irq_preinstall,
485 .irq_postinstall = tilcdc_irq_postinstall,
486 .irq_uninstall = tilcdc_irq_uninstall,
487 .get_vblank_counter = drm_vblank_count,
488 .enable_vblank = tilcdc_enable_vblank,
489 .disable_vblank = tilcdc_disable_vblank,
490 .gem_free_object = drm_gem_cma_free_object,
491 .gem_vm_ops = &drm_gem_cma_vm_ops,
492 .dumb_create = drm_gem_cma_dumb_create,
493 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
494 .dumb_destroy = drm_gem_cma_dumb_destroy,
495#ifdef CONFIG_DEBUG_FS
496 .debugfs_init = tilcdc_debugfs_init,
497 .debugfs_cleanup = tilcdc_debugfs_cleanup,
498#endif
499 .fops = &fops,
500 .name = "tilcdc",
501 .desc = "TI LCD Controller DRM",
502 .date = "20121205",
503 .major = 1,
504 .minor = 0,
505};
506
507/*
508 * Power management:
509 */
510
511#ifdef CONFIG_PM_SLEEP
512static int tilcdc_pm_suspend(struct device *dev)
513{
514 struct drm_device *ddev = dev_get_drvdata(dev);
515 struct tilcdc_drm_private *priv = ddev->dev_private;
516 unsigned i, n = 0;
517
518 drm_kms_helper_poll_disable(ddev);
519
520 /* Save register state: */
521 for (i = 0; i < ARRAY_SIZE(registers); i++)
522 if (registers[i].save && (priv->rev >= registers[i].rev))
523 priv->saved_register[n++] = tilcdc_read(ddev, registers[i].reg);
524
525 return 0;
526}
527
528static int tilcdc_pm_resume(struct device *dev)
529{
530 struct drm_device *ddev = dev_get_drvdata(dev);
531 struct tilcdc_drm_private *priv = ddev->dev_private;
532 unsigned i, n = 0;
533
534 /* Restore register state: */
535 for (i = 0; i < ARRAY_SIZE(registers); i++)
536 if (registers[i].save && (priv->rev >= registers[i].rev))
537 tilcdc_write(ddev, registers[i].reg, priv->saved_register[n++]);
538
539 drm_kms_helper_poll_enable(ddev);
540
541 return 0;
542}
543#endif
544
545static const struct dev_pm_ops tilcdc_pm_ops = {
546 SET_SYSTEM_SLEEP_PM_OPS(tilcdc_pm_suspend, tilcdc_pm_resume)
547};
548
549/*
550 * Platform driver:
551 */
552
553static int tilcdc_pdev_probe(struct platform_device *pdev)
554{
555 /* bail out early if no DT data: */
556 if (!pdev->dev.of_node) {
557 dev_err(&pdev->dev, "device-tree data is missing\n");
558 return -ENXIO;
559 }
560
561 return drm_platform_init(&tilcdc_driver, pdev);
562}
563
564static int tilcdc_pdev_remove(struct platform_device *pdev)
565{
566 drm_platform_exit(&tilcdc_driver, pdev);
567
568 return 0;
569}
570
571static struct of_device_id tilcdc_of_match[] = {
572 { .compatible = "ti,am33xx-tilcdc", },
573 { },
574};
575MODULE_DEVICE_TABLE(of, tilcdc_of_match);
576
577static struct platform_driver tilcdc_platform_driver = {
578 .probe = tilcdc_pdev_probe,
579 .remove = tilcdc_pdev_remove,
580 .driver = {
581 .owner = THIS_MODULE,
582 .name = "tilcdc",
583 .pm = &tilcdc_pm_ops,
584 .of_match_table = tilcdc_of_match,
585 },
586};
587
588static int __init tilcdc_drm_init(void)
589{
590 DBG("init");
591 tilcdc_tfp410_init();
592 tilcdc_slave_init();
593 tilcdc_panel_init();
594 return platform_driver_register(&tilcdc_platform_driver);
595}
596
597static void __exit tilcdc_drm_fini(void)
598{
599 DBG("fini");
600 tilcdc_tfp410_fini();
601 tilcdc_slave_fini();
602 tilcdc_panel_fini();
603 platform_driver_unregister(&tilcdc_platform_driver);
604}
605
606late_initcall(tilcdc_drm_init);
607module_exit(tilcdc_drm_fini);
608
609MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
610MODULE_DESCRIPTION("TI LCD Controller DRM Driver");
611MODULE_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_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
new file mode 100644
index 000000000000..580b74e2022b
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -0,0 +1,436 @@
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/pinctrl/pinmux.h>
19#include <linux/pinctrl/consumer.h>
20#include <linux/backlight.h>
21#include <video/display_timing.h>
22#include <video/of_display_timing.h>
23#include <video/videomode.h>
24
25#include "tilcdc_drv.h"
26
27struct panel_module {
28 struct tilcdc_module base;
29 struct tilcdc_panel_info *info;
30 struct display_timings *timings;
31 struct backlight_device *backlight;
32};
33#define to_panel_module(x) container_of(x, struct panel_module, base)
34
35
36/*
37 * Encoder:
38 */
39
40struct panel_encoder {
41 struct drm_encoder base;
42 struct panel_module *mod;
43};
44#define to_panel_encoder(x) container_of(x, struct panel_encoder, base)
45
46
47static void panel_encoder_destroy(struct drm_encoder *encoder)
48{
49 struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
50 drm_encoder_cleanup(encoder);
51 kfree(panel_encoder);
52}
53
54static void panel_encoder_dpms(struct drm_encoder *encoder, int mode)
55{
56 struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
57 struct backlight_device *backlight = panel_encoder->mod->backlight;
58
59 if (!backlight)
60 return;
61
62 backlight->props.power = mode == DRM_MODE_DPMS_ON
63 ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
64 backlight_update_status(backlight);
65}
66
67static bool panel_encoder_mode_fixup(struct drm_encoder *encoder,
68 const struct drm_display_mode *mode,
69 struct drm_display_mode *adjusted_mode)
70{
71 /* nothing needed */
72 return true;
73}
74
75static void panel_encoder_prepare(struct drm_encoder *encoder)
76{
77 struct panel_encoder *panel_encoder = to_panel_encoder(encoder);
78 panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
79 tilcdc_crtc_set_panel_info(encoder->crtc, panel_encoder->mod->info);
80}
81
82static void panel_encoder_commit(struct drm_encoder *encoder)
83{
84 panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
85}
86
87static void panel_encoder_mode_set(struct drm_encoder *encoder,
88 struct drm_display_mode *mode,
89 struct drm_display_mode *adjusted_mode)
90{
91 /* nothing needed */
92}
93
94static const struct drm_encoder_funcs panel_encoder_funcs = {
95 .destroy = panel_encoder_destroy,
96};
97
98static const struct drm_encoder_helper_funcs panel_encoder_helper_funcs = {
99 .dpms = panel_encoder_dpms,
100 .mode_fixup = panel_encoder_mode_fixup,
101 .prepare = panel_encoder_prepare,
102 .commit = panel_encoder_commit,
103 .mode_set = panel_encoder_mode_set,
104};
105
106static struct drm_encoder *panel_encoder_create(struct drm_device *dev,
107 struct panel_module *mod)
108{
109 struct panel_encoder *panel_encoder;
110 struct drm_encoder *encoder;
111 int ret;
112
113 panel_encoder = kzalloc(sizeof(*panel_encoder), GFP_KERNEL);
114 if (!panel_encoder) {
115 dev_err(dev->dev, "allocation failed\n");
116 return NULL;
117 }
118
119 panel_encoder->mod = mod;
120
121 encoder = &panel_encoder->base;
122 encoder->possible_crtcs = 1;
123
124 ret = drm_encoder_init(dev, encoder, &panel_encoder_funcs,
125 DRM_MODE_ENCODER_LVDS);
126 if (ret < 0)
127 goto fail;
128
129 drm_encoder_helper_add(encoder, &panel_encoder_helper_funcs);
130
131 return encoder;
132
133fail:
134 panel_encoder_destroy(encoder);
135 return NULL;
136}
137
138/*
139 * Connector:
140 */
141
142struct panel_connector {
143 struct drm_connector base;
144
145 struct drm_encoder *encoder; /* our connected encoder */
146 struct panel_module *mod;
147};
148#define to_panel_connector(x) container_of(x, struct panel_connector, base)
149
150
151static void panel_connector_destroy(struct drm_connector *connector)
152{
153 struct panel_connector *panel_connector = to_panel_connector(connector);
154 drm_connector_cleanup(connector);
155 kfree(panel_connector);
156}
157
158static enum drm_connector_status panel_connector_detect(
159 struct drm_connector *connector,
160 bool force)
161{
162 return connector_status_connected;
163}
164
165static int panel_connector_get_modes(struct drm_connector *connector)
166{
167 struct drm_device *dev = connector->dev;
168 struct panel_connector *panel_connector = to_panel_connector(connector);
169 struct display_timings *timings = panel_connector->mod->timings;
170 int i;
171
172 for (i = 0; i < timings->num_timings; i++) {
173 struct drm_display_mode *mode = drm_mode_create(dev);
174 struct videomode vm;
175
176 if (videomode_from_timing(timings, &vm, i))
177 break;
178
179 drm_display_mode_from_videomode(&vm, mode);
180
181 mode->type = DRM_MODE_TYPE_DRIVER;
182
183 if (timings->native_mode == i)
184 mode->type |= DRM_MODE_TYPE_PREFERRED;
185
186 drm_mode_set_name(mode);
187 drm_mode_probed_add(connector, mode);
188 }
189
190 return i;
191}
192
193static int panel_connector_mode_valid(struct drm_connector *connector,
194 struct drm_display_mode *mode)
195{
196 struct tilcdc_drm_private *priv = connector->dev->dev_private;
197 /* our only constraints are what the crtc can generate: */
198 return tilcdc_crtc_mode_valid(priv->crtc, mode);
199}
200
201static struct drm_encoder *panel_connector_best_encoder(
202 struct drm_connector *connector)
203{
204 struct panel_connector *panel_connector = to_panel_connector(connector);
205 return panel_connector->encoder;
206}
207
208static const struct drm_connector_funcs panel_connector_funcs = {
209 .destroy = panel_connector_destroy,
210 .dpms = drm_helper_connector_dpms,
211 .detect = panel_connector_detect,
212 .fill_modes = drm_helper_probe_single_connector_modes,
213};
214
215static const struct drm_connector_helper_funcs panel_connector_helper_funcs = {
216 .get_modes = panel_connector_get_modes,
217 .mode_valid = panel_connector_mode_valid,
218 .best_encoder = panel_connector_best_encoder,
219};
220
221static struct drm_connector *panel_connector_create(struct drm_device *dev,
222 struct panel_module *mod, struct drm_encoder *encoder)
223{
224 struct panel_connector *panel_connector;
225 struct drm_connector *connector;
226 int ret;
227
228 panel_connector = kzalloc(sizeof(*panel_connector), GFP_KERNEL);
229 if (!panel_connector) {
230 dev_err(dev->dev, "allocation failed\n");
231 return NULL;
232 }
233
234 panel_connector->encoder = encoder;
235 panel_connector->mod = mod;
236
237 connector = &panel_connector->base;
238
239 drm_connector_init(dev, connector, &panel_connector_funcs,
240 DRM_MODE_CONNECTOR_LVDS);
241 drm_connector_helper_add(connector, &panel_connector_helper_funcs);
242
243 connector->interlace_allowed = 0;
244 connector->doublescan_allowed = 0;
245
246 ret = drm_mode_connector_attach_encoder(connector, encoder);
247 if (ret)
248 goto fail;
249
250 drm_sysfs_connector_add(connector);
251
252 return connector;
253
254fail:
255 panel_connector_destroy(connector);
256 return NULL;
257}
258
259/*
260 * Module:
261 */
262
263static int panel_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
264{
265 struct panel_module *panel_mod = to_panel_module(mod);
266 struct tilcdc_drm_private *priv = dev->dev_private;
267 struct drm_encoder *encoder;
268 struct drm_connector *connector;
269
270 encoder = panel_encoder_create(dev, panel_mod);
271 if (!encoder)
272 return -ENOMEM;
273
274 connector = panel_connector_create(dev, panel_mod, encoder);
275 if (!connector)
276 return -ENOMEM;
277
278 priv->encoders[priv->num_encoders++] = encoder;
279 priv->connectors[priv->num_connectors++] = connector;
280
281 return 0;
282}
283
284static void panel_destroy(struct tilcdc_module *mod)
285{
286 struct panel_module *panel_mod = to_panel_module(mod);
287
288 if (panel_mod->timings) {
289 display_timings_release(panel_mod->timings);
290 kfree(panel_mod->timings);
291 }
292
293 tilcdc_module_cleanup(mod);
294 kfree(panel_mod->info);
295 kfree(panel_mod);
296}
297
298static const struct tilcdc_module_ops panel_module_ops = {
299 .modeset_init = panel_modeset_init,
300 .destroy = panel_destroy,
301};
302
303/*
304 * Device:
305 */
306
307/* maybe move this somewhere common if it is needed by other outputs? */
308static struct tilcdc_panel_info * of_get_panel_info(struct device_node *np)
309{
310 struct device_node *info_np;
311 struct tilcdc_panel_info *info;
312 int ret = 0;
313
314 if (!np) {
315 pr_err("%s: no devicenode given\n", __func__);
316 return NULL;
317 }
318
319 info_np = of_get_child_by_name(np, "panel-info");
320 if (!info_np) {
321 pr_err("%s: could not find panel-info node\n", __func__);
322 return NULL;
323 }
324
325 info = kzalloc(sizeof(*info), GFP_KERNEL);
326 if (!info) {
327 pr_err("%s: allocation failed\n", __func__);
328 return NULL;
329 }
330
331 ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias);
332 ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt);
333 ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz);
334 ret |= of_property_read_u32(info_np, "bpp", &info->bpp);
335 ret |= of_property_read_u32(info_np, "fdd", &info->fdd);
336 ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge);
337 ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl);
338 ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order);
339 ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th);
340
341 /* optional: */
342 info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode");
343 info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk");
344
345 if (ret) {
346 pr_err("%s: error reading panel-info properties\n", __func__);
347 kfree(info);
348 return NULL;
349 }
350
351 return info;
352}
353
354static struct of_device_id panel_of_match[];
355
356static int panel_probe(struct platform_device *pdev)
357{
358 struct device_node *node = pdev->dev.of_node;
359 struct panel_module *panel_mod;
360 struct tilcdc_module *mod;
361 struct pinctrl *pinctrl;
362 int ret = -EINVAL;
363
364
365 /* bail out early if no DT data: */
366 if (!node) {
367 dev_err(&pdev->dev, "device-tree data is missing\n");
368 return -ENXIO;
369 }
370
371 panel_mod = kzalloc(sizeof(*panel_mod), GFP_KERNEL);
372 if (!panel_mod)
373 return -ENOMEM;
374
375 mod = &panel_mod->base;
376
377 tilcdc_module_init(mod, "panel", &panel_module_ops);
378
379 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
380 if (IS_ERR(pinctrl))
381 dev_warn(&pdev->dev, "pins are not configured\n");
382
383
384 panel_mod->timings = of_get_display_timings(node);
385 if (!panel_mod->timings) {
386 dev_err(&pdev->dev, "could not get panel timings\n");
387 goto fail;
388 }
389
390 panel_mod->info = of_get_panel_info(node);
391 if (!panel_mod->info) {
392 dev_err(&pdev->dev, "could not get panel info\n");
393 goto fail;
394 }
395
396 panel_mod->backlight = of_find_backlight_by_node(node);
397 if (panel_mod->backlight)
398 dev_info(&pdev->dev, "found backlight\n");
399
400 return 0;
401
402fail:
403 panel_destroy(mod);
404 return ret;
405}
406
407static int panel_remove(struct platform_device *pdev)
408{
409 return 0;
410}
411
412static struct of_device_id panel_of_match[] = {
413 { .compatible = "ti,tilcdc,panel", },
414 { },
415};
416MODULE_DEVICE_TABLE(of, panel_of_match);
417
418struct platform_driver panel_driver = {
419 .probe = panel_probe,
420 .remove = panel_remove,
421 .driver = {
422 .owner = THIS_MODULE,
423 .name = "panel",
424 .of_match_table = panel_of_match,
425 },
426};
427
428int __init tilcdc_panel_init(void)
429{
430 return platform_driver_register(&panel_driver);
431}
432
433void __exit tilcdc_panel_fini(void)
434{
435 platform_driver_unregister(&panel_driver);
436}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.h b/drivers/gpu/drm/tilcdc/tilcdc_panel.h
new file mode 100644
index 000000000000..7db40aacc74a
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.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_PANEL_H__
19#define __TILCDC_PANEL_H__
20
21/* sub-module for generic lcd panel output */
22
23int tilcdc_panel_init(void);
24void tilcdc_panel_fini(void);
25
26#endif /* __TILCDC_PANEL_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_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
new file mode 100644
index 000000000000..568dc1c08e6c
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c
@@ -0,0 +1,376 @@
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/pinctrl/pinmux.h>
21#include <linux/pinctrl/consumer.h>
22#include <drm/drm_encoder_slave.h>
23
24#include "tilcdc_drv.h"
25
26struct slave_module {
27 struct tilcdc_module base;
28 struct i2c_adapter *i2c;
29};
30#define to_slave_module(x) container_of(x, struct slave_module, base)
31
32static const struct tilcdc_panel_info slave_info = {
33 .bpp = 16,
34 .ac_bias = 255,
35 .ac_bias_intrpt = 0,
36 .dma_burst_sz = 16,
37 .fdd = 0x80,
38 .tft_alt_mode = 0,
39 .sync_edge = 0,
40 .sync_ctrl = 1,
41 .raster_order = 0,
42};
43
44
45/*
46 * Encoder:
47 */
48
49struct slave_encoder {
50 struct drm_encoder_slave base;
51 struct slave_module *mod;
52};
53#define to_slave_encoder(x) container_of(to_encoder_slave(x), struct slave_encoder, base)
54
55static inline struct drm_encoder_slave_funcs *
56get_slave_funcs(struct drm_encoder *enc)
57{
58 return to_encoder_slave(enc)->slave_funcs;
59}
60
61static void slave_encoder_destroy(struct drm_encoder *encoder)
62{
63 struct slave_encoder *slave_encoder = to_slave_encoder(encoder);
64 if (get_slave_funcs(encoder))
65 get_slave_funcs(encoder)->destroy(encoder);
66 drm_encoder_cleanup(encoder);
67 kfree(slave_encoder);
68}
69
70static void slave_encoder_prepare(struct drm_encoder *encoder)
71{
72 drm_i2c_encoder_prepare(encoder);
73 tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info);
74}
75
76static const struct drm_encoder_funcs slave_encoder_funcs = {
77 .destroy = slave_encoder_destroy,
78};
79
80static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = {
81 .dpms = drm_i2c_encoder_dpms,
82 .mode_fixup = drm_i2c_encoder_mode_fixup,
83 .prepare = slave_encoder_prepare,
84 .commit = drm_i2c_encoder_commit,
85 .mode_set = drm_i2c_encoder_mode_set,
86 .save = drm_i2c_encoder_save,
87 .restore = drm_i2c_encoder_restore,
88};
89
90static const struct i2c_board_info info = {
91 I2C_BOARD_INFO("tda998x", 0x70)
92};
93
94static struct drm_encoder *slave_encoder_create(struct drm_device *dev,
95 struct slave_module *mod)
96{
97 struct slave_encoder *slave_encoder;
98 struct drm_encoder *encoder;
99 int ret;
100
101 slave_encoder = kzalloc(sizeof(*slave_encoder), GFP_KERNEL);
102 if (!slave_encoder) {
103 dev_err(dev->dev, "allocation failed\n");
104 return NULL;
105 }
106
107 slave_encoder->mod = mod;
108
109 encoder = &slave_encoder->base.base;
110 encoder->possible_crtcs = 1;
111
112 ret = drm_encoder_init(dev, encoder, &slave_encoder_funcs,
113 DRM_MODE_ENCODER_TMDS);
114 if (ret)
115 goto fail;
116
117 drm_encoder_helper_add(encoder, &slave_encoder_helper_funcs);
118
119 ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), mod->i2c, &info);
120 if (ret)
121 goto fail;
122
123 return encoder;
124
125fail:
126 slave_encoder_destroy(encoder);
127 return NULL;
128}
129
130/*
131 * Connector:
132 */
133
134struct slave_connector {
135 struct drm_connector base;
136
137 struct drm_encoder *encoder; /* our connected encoder */
138 struct slave_module *mod;
139};
140#define to_slave_connector(x) container_of(x, struct slave_connector, base)
141
142static void slave_connector_destroy(struct drm_connector *connector)
143{
144 struct slave_connector *slave_connector = to_slave_connector(connector);
145 drm_connector_cleanup(connector);
146 kfree(slave_connector);
147}
148
149static enum drm_connector_status slave_connector_detect(
150 struct drm_connector *connector,
151 bool force)
152{
153 struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
154 return get_slave_funcs(encoder)->detect(encoder, connector);
155}
156
157static int slave_connector_get_modes(struct drm_connector *connector)
158{
159 struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
160 return get_slave_funcs(encoder)->get_modes(encoder, connector);
161}
162
163static int slave_connector_mode_valid(struct drm_connector *connector,
164 struct drm_display_mode *mode)
165{
166 struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
167 struct tilcdc_drm_private *priv = connector->dev->dev_private;
168 int ret;
169
170 ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
171 if (ret != MODE_OK)
172 return ret;
173
174 return get_slave_funcs(encoder)->mode_valid(encoder, mode);
175}
176
177static struct drm_encoder *slave_connector_best_encoder(
178 struct drm_connector *connector)
179{
180 struct slave_connector *slave_connector = to_slave_connector(connector);
181 return slave_connector->encoder;
182}
183
184static int slave_connector_set_property(struct drm_connector *connector,
185 struct drm_property *property, uint64_t value)
186{
187 struct drm_encoder *encoder = to_slave_connector(connector)->encoder;
188 return get_slave_funcs(encoder)->set_property(encoder,
189 connector, property, value);
190}
191
192static const struct drm_connector_funcs slave_connector_funcs = {
193 .destroy = slave_connector_destroy,
194 .dpms = drm_helper_connector_dpms,
195 .detect = slave_connector_detect,
196 .fill_modes = drm_helper_probe_single_connector_modes,
197 .set_property = slave_connector_set_property,
198};
199
200static const struct drm_connector_helper_funcs slave_connector_helper_funcs = {
201 .get_modes = slave_connector_get_modes,
202 .mode_valid = slave_connector_mode_valid,
203 .best_encoder = slave_connector_best_encoder,
204};
205
206static struct drm_connector *slave_connector_create(struct drm_device *dev,
207 struct slave_module *mod, struct drm_encoder *encoder)
208{
209 struct slave_connector *slave_connector;
210 struct drm_connector *connector;
211 int ret;
212
213 slave_connector = kzalloc(sizeof(*slave_connector), GFP_KERNEL);
214 if (!slave_connector) {
215 dev_err(dev->dev, "allocation failed\n");
216 return NULL;
217 }
218
219 slave_connector->encoder = encoder;
220 slave_connector->mod = mod;
221
222 connector = &slave_connector->base;
223
224 drm_connector_init(dev, connector, &slave_connector_funcs,
225 DRM_MODE_CONNECTOR_HDMIA);
226 drm_connector_helper_add(connector, &slave_connector_helper_funcs);
227
228 connector->polled = DRM_CONNECTOR_POLL_CONNECT |
229 DRM_CONNECTOR_POLL_DISCONNECT;
230
231 connector->interlace_allowed = 0;
232 connector->doublescan_allowed = 0;
233
234 get_slave_funcs(encoder)->create_resources(encoder, connector);
235
236 ret = drm_mode_connector_attach_encoder(connector, encoder);
237 if (ret)
238 goto fail;
239
240 drm_sysfs_connector_add(connector);
241
242 return connector;
243
244fail:
245 slave_connector_destroy(connector);
246 return NULL;
247}
248
249/*
250 * Module:
251 */
252
253static int slave_modeset_init(struct tilcdc_module *mod, struct drm_device *dev)
254{
255 struct slave_module *slave_mod = to_slave_module(mod);
256 struct tilcdc_drm_private *priv = dev->dev_private;
257 struct drm_encoder *encoder;
258 struct drm_connector *connector;
259
260 encoder = slave_encoder_create(dev, slave_mod);
261 if (!encoder)
262 return -ENOMEM;
263
264 connector = slave_connector_create(dev, slave_mod, encoder);
265 if (!connector)
266 return -ENOMEM;
267
268 priv->encoders[priv->num_encoders++] = encoder;
269 priv->connectors[priv->num_connectors++] = connector;
270
271 return 0;
272}
273
274static void slave_destroy(struct tilcdc_module *mod)
275{
276 struct slave_module *slave_mod = to_slave_module(mod);
277
278 tilcdc_module_cleanup(mod);
279 kfree(slave_mod);
280}
281
282static const struct tilcdc_module_ops slave_module_ops = {
283 .modeset_init = slave_modeset_init,
284 .destroy = slave_destroy,
285};
286
287/*
288 * Device:
289 */
290
291static struct of_device_id slave_of_match[];
292
293static int slave_probe(struct platform_device *pdev)
294{
295 struct device_node *node = pdev->dev.of_node;
296 struct device_node *i2c_node;
297 struct slave_module *slave_mod;
298 struct tilcdc_module *mod;
299 struct pinctrl *pinctrl;
300 uint32_t i2c_phandle;
301 int ret = -EINVAL;
302
303 /* bail out early if no DT data: */
304 if (!node) {
305 dev_err(&pdev->dev, "device-tree data is missing\n");
306 return -ENXIO;
307 }
308
309 slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL);
310 if (!slave_mod)
311 return -ENOMEM;
312
313 mod = &slave_mod->base;
314
315 tilcdc_module_init(mod, "slave", &slave_module_ops);
316
317 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
318 if (IS_ERR(pinctrl))
319 dev_warn(&pdev->dev, "pins are not configured\n");
320
321 if (of_property_read_u32(node, "i2c", &i2c_phandle)) {
322 dev_err(&pdev->dev, "could not get i2c bus phandle\n");
323 goto fail;
324 }
325
326 i2c_node = of_find_node_by_phandle(i2c_phandle);
327 if (!i2c_node) {
328 dev_err(&pdev->dev, "could not get i2c bus node\n");
329 goto fail;
330 }
331
332 slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node);
333 if (!slave_mod->i2c) {
334 dev_err(&pdev->dev, "could not get i2c\n");
335 goto fail;
336 }
337
338 of_node_put(i2c_node);
339
340 return 0;
341
342fail:
343 slave_destroy(mod);
344 return ret;
345}
346
347static int slave_remove(struct platform_device *pdev)
348{
349 return 0;
350}
351
352static struct of_device_id slave_of_match[] = {
353 { .compatible = "ti,tilcdc,slave", },
354 { },
355};
356MODULE_DEVICE_TABLE(of, slave_of_match);
357
358struct platform_driver slave_driver = {
359 .probe = slave_probe,
360 .remove = slave_remove,
361 .driver = {
362 .owner = THIS_MODULE,
363 .name = "slave",
364 .of_match_table = slave_of_match,
365 },
366};
367
368int __init tilcdc_slave_init(void)
369{
370 return platform_driver_register(&slave_driver);
371}
372
373void __exit tilcdc_slave_fini(void)
374{
375 platform_driver_unregister(&slave_driver);
376}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.h b/drivers/gpu/drm/tilcdc/tilcdc_slave.h
new file mode 100644
index 000000000000..2f8504848320
--- /dev/null
+++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.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_SLAVE_H__
19#define __TILCDC_SLAVE_H__
20
21/* sub-module for i2c slave encoder output */
22
23int tilcdc_slave_init(void);
24void tilcdc_slave_fini(void);
25
26#endif /* __TILCDC_SLAVE_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__ */