aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-02-20 18:31:47 -0500
committerDave Airlie <airlied@redhat.com>2013-02-20 18:31:47 -0500
commitca18e1426bb2db987b67030256477c9571aebd09 (patch)
tree72e7cbe5f00f90390d00f5d3d4c9bdec79e48bbe
parent74e1697478ffdee0e12e48db024a9b3677fd8cee (diff)
parent0d4bbaf9f3e5b9f52150ddc5a4ee8b0ab83a440b (diff)
Merge branch 'tilcdc-next' of git://people.freedesktop.org/~robclark/linux into drm-next
KMS driver for TI LCD controller * 'tilcdc-next' of git://people.freedesktop.org/~robclark/linux: drm/tilcdc: add support for LCD panels (v5) drm/tilcdc: add encoder slave (v2) drm/i2c: nxp-tda998x (v3) drm/tilcdc: add TI LCD Controller DRM driver (v4) drm/nouveau: use i2c encoder helper wrappers drm: i2c encoder helper wrappers drm/cma: add debugfs helpers drm: small fix in drm_send_vblank_event() drm: Don't set the plane->fb to NULL on successfull set_plane drm/cma-helper: fixup compilation Conflicts: drivers/gpu/drm/Kconfig drivers/gpu/drm/Makefile drivers/gpu/drm/drm_fb_cma_helper.c
-rw-r--r--Documentation/devicetree/bindings/drm/tilcdc/panel.txt59
-rw-r--r--Documentation/devicetree/bindings/drm/tilcdc/slave.txt18
-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/drm_encoder_slave.c63
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c53
-rw-r--r--drivers/gpu/drm/drm_gem_cma_helper.c21
-rw-r--r--drivers/gpu/drm/drm_irq.c1
-rw-r--r--drivers/gpu/drm/i2c/Kconfig6
-rw-r--r--drivers/gpu/drm/i2c/Makefile3
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c906
-rw-r--r--drivers/gpu/drm/nouveau/nv04_tv.c39
-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
-rw-r--r--include/drm/drm_encoder_slave.h20
-rw-r--r--include/drm/drm_fb_cma_helper.h5
-rw-r--r--include/drm/drm_gem_cma_helper.h4
29 files changed, 4066 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/drm/tilcdc/panel.txt b/Documentation/devicetree/bindings/drm/tilcdc/panel.txt
new file mode 100644
index 000000000000..9301c330d1a6
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/tilcdc/panel.txt
@@ -0,0 +1,59 @@
1Device-Tree bindings for tilcdc DRM generic panel output driver
2
3Required properties:
4 - compatible: value should be "ti,tilcdc,panel".
5 - panel-info: configuration info to configure LCDC correctly for the panel
6 - ac-bias: AC Bias Pin Frequency
7 - ac-bias-intrpt: AC Bias Pin Transitions per Interrupt
8 - dma-burst-sz: DMA burst size
9 - bpp: Bits per pixel
10 - fdd: FIFO DMA Request Delay
11 - sync-edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling
12 - sync-ctrl: Horizontal and Vertical Sync: Control: 0=ignore
13 - raster-order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most
14 - fifo-th: DMA FIFO threshold
15 - display-timings: typical videomode of lcd panel. Multiple video modes
16 can be listed if the panel supports multiple timings, but the 'native-mode'
17 should be the preferred/default resolution. Refer to
18 Documentation/devicetree/bindings/video/display-timing.txt for display
19 timing binding details.
20
21Recommended properties:
22 - pinctrl-names, pinctrl-0: the pincontrol settings to configure
23 muxing properly for pins that connect to TFP410 device
24
25Example:
26
27 /* Settings for CDTech_S035Q01 / LCD3 cape: */
28 lcd3 {
29 compatible = "ti,tilcdc,panel";
30 pinctrl-names = "default";
31 pinctrl-0 = <&bone_lcd3_cape_lcd_pins>;
32 panel-info {
33 ac-bias = <255>;
34 ac-bias-intrpt = <0>;
35 dma-burst-sz = <16>;
36 bpp = <16>;
37 fdd = <0x80>;
38 sync-edge = <0>;
39 sync-ctrl = <1>;
40 raster-order = <0>;
41 fifo-th = <0>;
42 };
43 display-timings {
44 native-mode = <&timing0>;
45 timing0: 320x240 {
46 hactive = <320>;
47 vactive = <240>;
48 hback-porch = <21>;
49 hfront-porch = <58>;
50 hsync-len = <47>;
51 vback-porch = <11>;
52 vfront-porch = <23>;
53 vsync-len = <2>;
54 clock-frequency = <8000000>;
55 hsync-active = <0>;
56 vsync-active = <0>;
57 };
58 };
59 };
diff --git a/Documentation/devicetree/bindings/drm/tilcdc/slave.txt b/Documentation/devicetree/bindings/drm/tilcdc/slave.txt
new file mode 100644
index 000000000000..3d2c52460dca
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/tilcdc/slave.txt
@@ -0,0 +1,18 @@
1Device-Tree bindings for tilcdc DRM encoder slave output driver
2
3Required properties:
4 - compatible: value should be "ti,tilcdc,slave".
5 - i2c: the phandle for the i2c device the encoder slave is connected to
6
7Recommended properties:
8 - pinctrl-names, pinctrl-0: the pincontrol settings to configure
9 muxing properly for pins that connect to TFP410 device
10
11Example:
12
13 hdmi {
14 compatible = "ti,tilcdc,slave";
15 i2c = <&i2c0>;
16 pinctrl-names = "default";
17 pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
18 };
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 0ce5f52ac56e..f8dae851130c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -217,3 +217,5 @@ source "drivers/gpu/drm/shmobile/Kconfig"
217source "drivers/gpu/drm/tegra/Kconfig" 217source "drivers/gpu/drm/tegra/Kconfig"
218 218
219source "drivers/gpu/drm/omapdrm/Kconfig" 219source "drivers/gpu/drm/omapdrm/Kconfig"
220
221source "drivers/gpu/drm/tilcdc/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index b6b43cbc18e4..0d59b24f8d23 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -51,4 +51,5 @@ obj-$(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_OMAP) += omapdrm/ 53obj-$(CONFIG_DRM_OMAP) += omapdrm/
54obj-$(CONFIG_DRM_TILCDC) += tilcdc/
54obj-y += i2c/ 55obj-y += i2c/
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c
index 63e733408b6d..48c52f7df4e6 100644
--- a/drivers/gpu/drm/drm_encoder_slave.c
+++ b/drivers/gpu/drm/drm_encoder_slave.c
@@ -123,3 +123,66 @@ void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
123 module_put(module); 123 module_put(module);
124} 124}
125EXPORT_SYMBOL(drm_i2c_encoder_destroy); 125EXPORT_SYMBOL(drm_i2c_encoder_destroy);
126
127/*
128 * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
129 */
130
131static inline struct drm_encoder_slave_funcs *
132get_slave_funcs(struct drm_encoder *enc)
133{
134 return to_encoder_slave(enc)->slave_funcs;
135}
136
137void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode)
138{
139 get_slave_funcs(encoder)->dpms(encoder, mode);
140}
141EXPORT_SYMBOL(drm_i2c_encoder_dpms);
142
143bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
144 const struct drm_display_mode *mode,
145 struct drm_display_mode *adjusted_mode)
146{
147 return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode);
148}
149EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup);
150
151void drm_i2c_encoder_prepare(struct drm_encoder *encoder)
152{
153 drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
154}
155EXPORT_SYMBOL(drm_i2c_encoder_prepare);
156
157void drm_i2c_encoder_commit(struct drm_encoder *encoder)
158{
159 drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
160}
161EXPORT_SYMBOL(drm_i2c_encoder_commit);
162
163void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
164 struct drm_display_mode *mode,
165 struct drm_display_mode *adjusted_mode)
166{
167 get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode);
168}
169EXPORT_SYMBOL(drm_i2c_encoder_mode_set);
170
171enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
172 struct drm_connector *connector)
173{
174 return get_slave_funcs(encoder)->detect(encoder, connector);
175}
176EXPORT_SYMBOL(drm_i2c_encoder_detect);
177
178void drm_i2c_encoder_save(struct drm_encoder *encoder)
179{
180 get_slave_funcs(encoder)->save(encoder);
181}
182EXPORT_SYMBOL(drm_i2c_encoder_save);
183
184void drm_i2c_encoder_restore(struct drm_encoder *encoder)
185{
186 get_slave_funcs(encoder)->restore(encoder);
187}
188EXPORT_SYMBOL(drm_i2c_encoder_restore);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 1c8549dae99a..0b5af7d0edb1 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -180,6 +180,59 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
180} 180}
181EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); 181EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
182 182
183#ifdef CONFIG_DEBUG_FS
184/**
185 * drm_fb_cma_describe() - Helper to dump information about a single
186 * CMA framebuffer object
187 */
188void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
189{
190 struct drm_fb_cma *fb_cma = to_fb_cma(fb);
191 int i, n = drm_format_num_planes(fb->pixel_format);
192
193 seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
194 (char *)&fb->pixel_format);
195
196 for (i = 0; i < n; i++) {
197 seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
198 i, fb->offsets[i], fb->pitches[i]);
199 drm_gem_cma_describe(fb_cma->obj[i], m);
200 }
201}
202EXPORT_SYMBOL_GPL(drm_fb_cma_describe);
203
204/**
205 * drm_fb_cma_debugfs_show() - Helper to list CMA framebuffer objects
206 * in debugfs.
207 */
208int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg)
209{
210 struct drm_info_node *node = (struct drm_info_node *) m->private;
211 struct drm_device *dev = node->minor->dev;
212 struct drm_framebuffer *fb;
213 int ret;
214
215 ret = mutex_lock_interruptible(&dev->mode_config.mutex);
216 if (ret)
217 return ret;
218
219 ret = mutex_lock_interruptible(&dev->struct_mutex);
220 if (ret) {
221 mutex_unlock(&dev->mode_config.mutex);
222 return ret;
223 }
224
225 list_for_each_entry(fb, &dev->mode_config.fb_list, head)
226 drm_fb_cma_describe(fb, m);
227
228 mutex_unlock(&dev->struct_mutex);
229 mutex_unlock(&dev->mode_config.mutex);
230
231 return 0;
232}
233EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
234#endif
235
183static struct fb_ops drm_fbdev_cma_ops = { 236static struct fb_ops drm_fbdev_cma_ops = {
184 .owner = THIS_MODULE, 237 .owner = THIS_MODULE,
185 .fb_fillrect = sys_fillrect, 238 .fb_fillrect = sys_fillrect,
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
index 1aa8fee1e865..0a7e011509bd 100644
--- a/drivers/gpu/drm/drm_gem_cma_helper.c
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -249,3 +249,24 @@ int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
249 return drm_gem_handle_delete(file_priv, handle); 249 return drm_gem_handle_delete(file_priv, handle);
250} 250}
251EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy); 251EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy);
252
253#ifdef CONFIG_DEBUG_FS
254void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m)
255{
256 struct drm_gem_object *obj = &cma_obj->base;
257 struct drm_device *dev = obj->dev;
258 uint64_t off = 0;
259
260 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
261
262 if (obj->map_list.map)
263 off = (uint64_t)obj->map_list.hash.key;
264
265 seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d",
266 obj->name, obj->refcount.refcount.counter,
267 off, cma_obj->paddr, cma_obj->vaddr, obj->size);
268
269 seq_printf(m, "\n");
270}
271EXPORT_SYMBOL_GPL(drm_gem_cma_describe);
272#endif
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 38e79927b2d7..a6a8643a6a77 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -867,6 +867,7 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc,
867 867
868 now = get_drm_timestamp(); 868 now = get_drm_timestamp();
869 } 869 }
870 e->pipe = crtc;
870 send_vblank_event(dev, e, seq, &now); 871 send_vblank_event(dev, e, seq, &now);
871} 872}
872EXPORT_SYMBOL(drm_send_vblank_event); 873EXPORT_SYMBOL(drm_send_vblank_event);
diff --git a/drivers/gpu/drm/i2c/Kconfig b/drivers/gpu/drm/i2c/Kconfig
index 16118363509a..4d341db462a2 100644
--- a/drivers/gpu/drm/i2c/Kconfig
+++ b/drivers/gpu/drm/i2c/Kconfig
@@ -19,4 +19,10 @@ config DRM_I2C_SIL164
19 when used in pairs) TMDS transmitters, used in some nVidia 19 when used in pairs) TMDS transmitters, used in some nVidia
20 video cards. 20 video cards.
21 21
22config DRM_I2C_NXP_TDA998X
23 tristate "NXP Semiconductors TDA998X HDMI encoder"
24 default m if DRM_TILCDC
25 help
26 Support for NXP Semiconductors TDA998X HDMI encoders.
27
22endmenu 28endmenu
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 92862563e7ee..43aa33baebed 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
5 5
6sil164-y := sil164_drv.o 6sil164-y := sil164_drv.o
7obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o 7obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
8
9tda998x-y := tda998x_drv.o
10obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
new file mode 100644
index 000000000000..e68b58a1aaf9
--- /dev/null
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -0,0 +1,906 @@
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
19
20#include <linux/module.h>
21
22#include <drm/drmP.h>
23#include <drm/drm_crtc_helper.h>
24#include <drm/drm_encoder_slave.h>
25#include <drm/drm_edid.h>
26
27
28#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
29
30struct tda998x_priv {
31 struct i2c_client *cec;
32 uint16_t rev;
33 uint8_t current_page;
34 int dpms;
35};
36
37#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
38
39/* The TDA9988 series of devices use a paged register scheme.. to simplify
40 * things we encode the page # in upper bits of the register #. To read/
41 * write a given register, we need to make sure CURPAGE register is set
42 * appropriately. Which implies reads/writes are not atomic. Fun!
43 */
44
45#define REG(page, addr) (((page) << 8) | (addr))
46#define REG2ADDR(reg) ((reg) & 0xff)
47#define REG2PAGE(reg) (((reg) >> 8) & 0xff)
48
49#define REG_CURPAGE 0xff /* write */
50
51
52/* Page 00h: General Control */
53#define REG_VERSION_LSB REG(0x00, 0x00) /* read */
54#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */
55# define MAIN_CNTRL0_SR (1 << 0)
56# define MAIN_CNTRL0_DECS (1 << 1)
57# define MAIN_CNTRL0_DEHS (1 << 2)
58# define MAIN_CNTRL0_CECS (1 << 3)
59# define MAIN_CNTRL0_CEHS (1 << 4)
60# define MAIN_CNTRL0_SCALER (1 << 7)
61#define REG_VERSION_MSB REG(0x00, 0x02) /* read */
62#define REG_SOFTRESET REG(0x00, 0x0a) /* write */
63# define SOFTRESET_AUDIO (1 << 0)
64# define SOFTRESET_I2C_MASTER (1 << 1)
65#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */
66#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */
67#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */
68# define I2C_MASTER_DIS_MM (1 << 0)
69# define I2C_MASTER_DIS_FILT (1 << 1)
70# define I2C_MASTER_APP_STRT_LAT (1 << 2)
71#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
72#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
73#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */
74# define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
75#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */
76#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */
77#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */
78#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */
79#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */
80# define VIP_CNTRL_0_MIRR_A (1 << 7)
81# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4)
82# define VIP_CNTRL_0_MIRR_B (1 << 3)
83# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0)
84#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */
85# define VIP_CNTRL_1_MIRR_C (1 << 7)
86# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4)
87# define VIP_CNTRL_1_MIRR_D (1 << 3)
88# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0)
89#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */
90# define VIP_CNTRL_2_MIRR_E (1 << 7)
91# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4)
92# define VIP_CNTRL_2_MIRR_F (1 << 3)
93# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0)
94#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */
95# define VIP_CNTRL_3_X_TGL (1 << 0)
96# define VIP_CNTRL_3_H_TGL (1 << 1)
97# define VIP_CNTRL_3_V_TGL (1 << 2)
98# define VIP_CNTRL_3_EMB (1 << 3)
99# define VIP_CNTRL_3_SYNC_DE (1 << 4)
100# define VIP_CNTRL_3_SYNC_HS (1 << 5)
101# define VIP_CNTRL_3_DE_INT (1 << 6)
102# define VIP_CNTRL_3_EDGE (1 << 7)
103#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */
104# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0)
105# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2)
106# define VIP_CNTRL_4_CCIR656 (1 << 4)
107# define VIP_CNTRL_4_656_ALT (1 << 5)
108# define VIP_CNTRL_4_TST_656 (1 << 6)
109# define VIP_CNTRL_4_TST_PAT (1 << 7)
110#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
111# define VIP_CNTRL_5_CKCASE (1 << 0)
112# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
113#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
114# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
115# define MAT_CONTRL_MAT_BP (1 << 2)
116#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */
117#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */
118#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */
119#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */
120#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */
121#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */
122#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */
123#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */
124#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */
125#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */
126#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */
127#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */
128#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */
129#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */
130#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */
131#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */
132#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */
133#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */
134#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */
135#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */
136#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */
137#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */
138#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */
139#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */
140#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */
141#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */
142#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */
143#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */
144#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */
145#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */
146#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */
147#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */
148#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */
149#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */
150# define TBG_CNTRL_0_FRAME_DIS (1 << 5)
151# define TBG_CNTRL_0_SYNC_MTHD (1 << 6)
152# define TBG_CNTRL_0_SYNC_ONCE (1 << 7)
153#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */
154# define TBG_CNTRL_1_VH_TGL_0 (1 << 0)
155# define TBG_CNTRL_1_VH_TGL_1 (1 << 1)
156# define TBG_CNTRL_1_VH_TGL_2 (1 << 2)
157# define TBG_CNTRL_1_VHX_EXT_DE (1 << 3)
158# define TBG_CNTRL_1_VHX_EXT_HS (1 << 4)
159# define TBG_CNTRL_1_VHX_EXT_VS (1 << 5)
160# define TBG_CNTRL_1_DWIN_DIS (1 << 6)
161#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */
162#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */
163# define HVF_CNTRL_0_SM (1 << 7)
164# define HVF_CNTRL_0_RWB (1 << 6)
165# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2)
166# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0)
167#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */
168# define HVF_CNTRL_1_FOR (1 << 0)
169# define HVF_CNTRL_1_YUVBLK (1 << 1)
170# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2)
171# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
172# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
173#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
174
175
176/* Page 02h: PLL settings */
177#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
178# define PLL_SERIAL_1_SRL_FDN (1 << 0)
179# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1)
180# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6)
181#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */
182# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0)
183# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4)
184#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */
185# define PLL_SERIAL_3_SRL_CCIR (1 << 0)
186# define PLL_SERIAL_3_SRL_DE (1 << 2)
187# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4)
188#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */
189#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */
190#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */
191#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */
192#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */
193#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */
194#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */
195#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */
196#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */
197#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */
198# define SEL_CLK_SEL_CLK1 (1 << 0)
199# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1)
200# define SEL_CLK_ENA_SC_CLK (1 << 3)
201#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */
202
203
204/* Page 09h: EDID Control */
205#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */
206/* next 127 successive registers are the EDID block */
207#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */
208#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */
209#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */
210#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */
211#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */
212
213
214/* Page 10h: information frames and packets */
215
216
217/* Page 11h: audio settings and content info packets */
218#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
219# define AIP_CNTRL_0_RST_FIFO (1 << 0)
220# define AIP_CNTRL_0_SWAP (1 << 1)
221# define AIP_CNTRL_0_LAYOUT (1 << 2)
222# define AIP_CNTRL_0_ACR_MAN (1 << 5)
223# define AIP_CNTRL_0_RST_CTS (1 << 6)
224#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
225# define ENC_CNTRL_RST_ENC (1 << 0)
226# define ENC_CNTRL_RST_SEL (1 << 1)
227# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
228
229
230/* Page 12h: HDCP and OTP */
231#define REG_TX3 REG(0x12, 0x9a) /* read/write */
232#define REG_TX33 REG(0x12, 0xb8) /* read/write */
233# define TX33_HDMI (1 << 1)
234
235
236/* Page 13h: Gamut related metadata packets */
237
238
239
240/* CEC registers: (not paged)
241 */
242#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */
243# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
244# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6)
245# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
246# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0)
247#define REG_CEC_RXSHPDLEV 0xfe /* read */
248# define CEC_RXSHPDLEV_RXSENS (1 << 0)
249# define CEC_RXSHPDLEV_HPD (1 << 1)
250
251#define REG_CEC_ENAMODS 0xff /* read/write */
252# define CEC_ENAMODS_DIS_FRO (1 << 6)
253# define CEC_ENAMODS_DIS_CCLK (1 << 5)
254# define CEC_ENAMODS_EN_RXSENS (1 << 2)
255# define CEC_ENAMODS_EN_HDMI (1 << 1)
256# define CEC_ENAMODS_EN_CEC (1 << 0)
257
258
259/* Device versions: */
260#define TDA9989N2 0x0101
261#define TDA19989 0x0201
262#define TDA19989N2 0x0202
263#define TDA19988 0x0301
264
265static void
266cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val)
267{
268 struct i2c_client *client = to_tda998x_priv(encoder)->cec;
269 uint8_t buf[] = {addr, val};
270 int ret;
271
272 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
273 if (ret < 0)
274 dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
275}
276
277static uint8_t
278cec_read(struct drm_encoder *encoder, uint8_t addr)
279{
280 struct i2c_client *client = to_tda998x_priv(encoder)->cec;
281 uint8_t val;
282 int ret;
283
284 ret = i2c_master_send(client, &addr, sizeof(addr));
285 if (ret < 0)
286 goto fail;
287
288 ret = i2c_master_recv(client, &val, sizeof(val));
289 if (ret < 0)
290 goto fail;
291
292 return val;
293
294fail:
295 dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr);
296 return 0;
297}
298
299static void
300set_page(struct drm_encoder *encoder, uint16_t reg)
301{
302 struct tda998x_priv *priv = to_tda998x_priv(encoder);
303
304 if (REG2PAGE(reg) != priv->current_page) {
305 struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
306 uint8_t buf[] = {
307 REG_CURPAGE, REG2PAGE(reg)
308 };
309 int ret = i2c_master_send(client, buf, sizeof(buf));
310 if (ret < 0)
311 dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret);
312
313 priv->current_page = REG2PAGE(reg);
314 }
315}
316
317static int
318reg_read_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt)
319{
320 struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
321 uint8_t addr = REG2ADDR(reg);
322 int ret;
323
324 set_page(encoder, reg);
325
326 ret = i2c_master_send(client, &addr, sizeof(addr));
327 if (ret < 0)
328 goto fail;
329
330 ret = i2c_master_recv(client, buf, cnt);
331 if (ret < 0)
332 goto fail;
333
334 return ret;
335
336fail:
337 dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg);
338 return ret;
339}
340
341static uint8_t
342reg_read(struct drm_encoder *encoder, uint16_t reg)
343{
344 uint8_t val = 0;
345 reg_read_range(encoder, reg, &val, sizeof(val));
346 return val;
347}
348
349static void
350reg_write(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
351{
352 struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
353 uint8_t buf[] = {REG2ADDR(reg), val};
354 int ret;
355
356 set_page(encoder, reg);
357
358 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
359 if (ret < 0)
360 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
361}
362
363static void
364reg_write16(struct drm_encoder *encoder, uint16_t reg, uint16_t val)
365{
366 struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
367 uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
368 int ret;
369
370 set_page(encoder, reg);
371
372 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
373 if (ret < 0)
374 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
375}
376
377static void
378reg_set(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
379{
380 reg_write(encoder, reg, reg_read(encoder, reg) | val);
381}
382
383static void
384reg_clear(struct drm_encoder *encoder, uint16_t reg, uint8_t val)
385{
386 reg_write(encoder, reg, reg_read(encoder, reg) & ~val);
387}
388
389static void
390tda998x_reset(struct drm_encoder *encoder)
391{
392 /* reset audio and i2c master: */
393 reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
394 msleep(50);
395 reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
396 msleep(50);
397
398 /* reset transmitter: */
399 reg_set(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
400 reg_clear(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
401
402 /* PLL registers common configuration */
403 reg_write(encoder, REG_PLL_SERIAL_1, 0x00);
404 reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
405 reg_write(encoder, REG_PLL_SERIAL_3, 0x00);
406 reg_write(encoder, REG_SERIALIZER, 0x00);
407 reg_write(encoder, REG_BUFFER_OUT, 0x00);
408 reg_write(encoder, REG_PLL_SCG1, 0x00);
409 reg_write(encoder, REG_AUDIO_DIV, 0x03);
410 reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
411 reg_write(encoder, REG_PLL_SCGN1, 0xfa);
412 reg_write(encoder, REG_PLL_SCGN2, 0x00);
413 reg_write(encoder, REG_PLL_SCGR1, 0x5b);
414 reg_write(encoder, REG_PLL_SCGR2, 0x00);
415 reg_write(encoder, REG_PLL_SCG2, 0x10);
416}
417
418/* DRM encoder functions */
419
420static void
421tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
422{
423}
424
425static void
426tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
427{
428 struct tda998x_priv *priv = to_tda998x_priv(encoder);
429
430 /* we only care about on or off: */
431 if (mode != DRM_MODE_DPMS_ON)
432 mode = DRM_MODE_DPMS_OFF;
433
434 if (mode == priv->dpms)
435 return;
436
437 switch (mode) {
438 case DRM_MODE_DPMS_ON:
439 /* enable audio and video ports */
440 reg_write(encoder, REG_ENA_AP, 0xff);
441 reg_write(encoder, REG_ENA_VP_0, 0xff);
442 reg_write(encoder, REG_ENA_VP_1, 0xff);
443 reg_write(encoder, REG_ENA_VP_2, 0xff);
444 /* set muxing after enabling ports: */
445 reg_write(encoder, REG_VIP_CNTRL_0,
446 VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3));
447 reg_write(encoder, REG_VIP_CNTRL_1,
448 VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1));
449 reg_write(encoder, REG_VIP_CNTRL_2,
450 VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5));
451 break;
452 case DRM_MODE_DPMS_OFF:
453 /* disable audio and video ports */
454 reg_write(encoder, REG_ENA_AP, 0x00);
455 reg_write(encoder, REG_ENA_VP_0, 0x00);
456 reg_write(encoder, REG_ENA_VP_1, 0x00);
457 reg_write(encoder, REG_ENA_VP_2, 0x00);
458 break;
459 }
460
461 priv->dpms = mode;
462}
463
464static void
465tda998x_encoder_save(struct drm_encoder *encoder)
466{
467 DBG("");
468}
469
470static void
471tda998x_encoder_restore(struct drm_encoder *encoder)
472{
473 DBG("");
474}
475
476static bool
477tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
478 const struct drm_display_mode *mode,
479 struct drm_display_mode *adjusted_mode)
480{
481 return true;
482}
483
484static int
485tda998x_encoder_mode_valid(struct drm_encoder *encoder,
486 struct drm_display_mode *mode)
487{
488 return MODE_OK;
489}
490
491static void
492tda998x_encoder_mode_set(struct drm_encoder *encoder,
493 struct drm_display_mode *mode,
494 struct drm_display_mode *adjusted_mode)
495{
496 struct tda998x_priv *priv = to_tda998x_priv(encoder);
497 uint16_t hs_start, hs_end, line_start, line_end;
498 uint16_t vwin_start, vwin_end, de_start, de_end;
499 uint16_t ref_pix, ref_line, pix_start2;
500 uint8_t reg, div, rep;
501
502 hs_start = mode->hsync_start - mode->hdisplay;
503 hs_end = mode->hsync_end - mode->hdisplay;
504 line_start = 1;
505 line_end = 1 + mode->vsync_end - mode->vsync_start;
506 vwin_start = mode->vtotal - mode->vsync_start;
507 vwin_end = vwin_start + mode->vdisplay;
508 de_start = mode->htotal - mode->hdisplay;
509 de_end = mode->htotal;
510
511 pix_start2 = 0;
512 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
513 pix_start2 = (mode->htotal / 2) + hs_start;
514
515 /* TODO how is this value calculated? It is 2 for all common
516 * formats in the tables in out of tree nxp driver (assuming
517 * I've properly deciphered their byzantine table system)
518 */
519 ref_line = 2;
520
521 /* this might changes for other color formats from the CRTC: */
522 ref_pix = 3 + hs_start;
523
524 div = 148500 / mode->clock;
525
526 DBG("clock=%d, div=%u", mode->clock, div);
527 DBG("hs_start=%u, hs_end=%u, line_start=%u, line_end=%u",
528 hs_start, hs_end, line_start, line_end);
529 DBG("vwin_start=%u, vwin_end=%u, de_start=%u, de_end=%u",
530 vwin_start, vwin_end, de_start, de_end);
531 DBG("ref_line=%u, ref_pix=%u, pix_start2=%u",
532 ref_line, ref_pix, pix_start2);
533
534 /* mute the audio FIFO: */
535 reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
536
537 /* set HDMI HDCP mode off: */
538 reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
539 reg_clear(encoder, REG_TX33, TX33_HDMI);
540
541 reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
542 /* no pre-filter or interpolator: */
543 reg_write(encoder, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
544 HVF_CNTRL_0_INTPOL(0));
545 reg_write(encoder, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
546 reg_write(encoder, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
547 VIP_CNTRL_4_BLC(0));
548 reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
549
550 reg_clear(encoder, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
551 reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
552 reg_write(encoder, REG_SERIALIZER, 0);
553 reg_write(encoder, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
554
555 /* TODO enable pixel repeat for pixel rates less than 25Msamp/s */
556 rep = 0;
557 reg_write(encoder, REG_RPT_CNTRL, 0);
558 reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
559 SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
560
561 reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
562 PLL_SERIAL_2_SRL_PR(rep));
563
564 reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, pix_start2);
565 reg_write16(encoder, REG_VS_PIX_END_2_MSB, pix_start2);
566
567 /* set color matrix bypass flag: */
568 reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP);
569
570 /* set BIAS tmds value: */
571 reg_write(encoder, REG_ANA_GENERAL, 0x09);
572
573 reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
574
575 reg_write(encoder, REG_VIP_CNTRL_3, 0);
576 reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS);
577 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
578 reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL);
579
580 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
581 reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
582
583 reg_write(encoder, REG_VIDFORMAT, 0x00);
584 reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1);
585 reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1);
586 reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start);
587 reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end);
588 reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start);
589 reg_write16(encoder, REG_VS_PIX_END_1_MSB, hs_start);
590 reg_write16(encoder, REG_HS_PIX_START_MSB, hs_start);
591 reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_end);
592 reg_write16(encoder, REG_VWIN_START_1_MSB, vwin_start);
593 reg_write16(encoder, REG_VWIN_END_1_MSB, vwin_end);
594 reg_write16(encoder, REG_DE_START_MSB, de_start);
595 reg_write16(encoder, REG_DE_STOP_MSB, de_end);
596
597 if (priv->rev == TDA19988) {
598 /* let incoming pixels fill the active space (if any) */
599 reg_write(encoder, REG_ENABLE_SPACE, 0x01);
600 }
601
602 reg_write16(encoder, REG_REFPIX_MSB, ref_pix);
603 reg_write16(encoder, REG_REFLINE_MSB, ref_line);
604
605 reg = TBG_CNTRL_1_VHX_EXT_DE |
606 TBG_CNTRL_1_VHX_EXT_HS |
607 TBG_CNTRL_1_VHX_EXT_VS |
608 TBG_CNTRL_1_DWIN_DIS | /* HDCP off */
609 TBG_CNTRL_1_VH_TGL_2;
610 if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC))
611 reg |= TBG_CNTRL_1_VH_TGL_0;
612 reg_set(encoder, REG_TBG_CNTRL_1, reg);
613
614 /* must be last register set: */
615 reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
616}
617
618static enum drm_connector_status
619tda998x_encoder_detect(struct drm_encoder *encoder,
620 struct drm_connector *connector)
621{
622 uint8_t val = cec_read(encoder, REG_CEC_RXSHPDLEV);
623 return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
624 connector_status_disconnected;
625}
626
627static int
628read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
629{
630 uint8_t offset, segptr;
631 int ret, i;
632
633 /* enable EDID read irq: */
634 reg_set(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
635
636 offset = (blk & 1) ? 128 : 0;
637 segptr = blk / 2;
638
639 reg_write(encoder, REG_DDC_ADDR, 0xa0);
640 reg_write(encoder, REG_DDC_OFFS, offset);
641 reg_write(encoder, REG_DDC_SEGM_ADDR, 0x60);
642 reg_write(encoder, REG_DDC_SEGM, segptr);
643
644 /* enable reading EDID: */
645 reg_write(encoder, REG_EDID_CTRL, 0x1);
646
647 /* flag must be cleared by sw: */
648 reg_write(encoder, REG_EDID_CTRL, 0x0);
649
650 /* wait for block read to complete: */
651 for (i = 100; i > 0; i--) {
652 uint8_t val = reg_read(encoder, REG_INT_FLAGS_2);
653 if (val & INT_FLAGS_2_EDID_BLK_RD)
654 break;
655 msleep(1);
656 }
657
658 if (i == 0)
659 return -ETIMEDOUT;
660
661 ret = reg_read_range(encoder, REG_EDID_DATA_0, buf, EDID_LENGTH);
662 if (ret != EDID_LENGTH) {
663 dev_err(encoder->dev->dev, "failed to read edid block %d: %d",
664 blk, ret);
665 return ret;
666 }
667
668 reg_clear(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
669
670 return 0;
671}
672
673static uint8_t *
674do_get_edid(struct drm_encoder *encoder)
675{
676 int j = 0, valid_extensions = 0;
677 uint8_t *block, *new;
678 bool print_bad_edid = drm_debug & DRM_UT_KMS;
679
680 if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
681 return NULL;
682
683 /* base block fetch */
684 if (read_edid_block(encoder, block, 0))
685 goto fail;
686
687 if (!drm_edid_block_valid(block, 0, print_bad_edid))
688 goto fail;
689
690 /* if there's no extensions, we're done */
691 if (block[0x7e] == 0)
692 return block;
693
694 new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
695 if (!new)
696 goto fail;
697 block = new;
698
699 for (j = 1; j <= block[0x7e]; j++) {
700 uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
701 if (read_edid_block(encoder, ext_block, j))
702 goto fail;
703
704 if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
705 goto fail;
706
707 valid_extensions++;
708 }
709
710 if (valid_extensions != block[0x7e]) {
711 block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
712 block[0x7e] = valid_extensions;
713 new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
714 if (!new)
715 goto fail;
716 block = new;
717 }
718
719 return block;
720
721fail:
722 dev_warn(encoder->dev->dev, "failed to read EDID\n");
723 kfree(block);
724 return NULL;
725}
726
727static int
728tda998x_encoder_get_modes(struct drm_encoder *encoder,
729 struct drm_connector *connector)
730{
731 struct edid *edid = (struct edid *)do_get_edid(encoder);
732 int n = 0;
733
734 if (edid) {
735 drm_mode_connector_update_edid_property(connector, edid);
736 n = drm_add_edid_modes(connector, edid);
737 kfree(edid);
738 }
739
740 return n;
741}
742
743static int
744tda998x_encoder_create_resources(struct drm_encoder *encoder,
745 struct drm_connector *connector)
746{
747 DBG("");
748 return 0;
749}
750
751static int
752tda998x_encoder_set_property(struct drm_encoder *encoder,
753 struct drm_connector *connector,
754 struct drm_property *property,
755 uint64_t val)
756{
757 DBG("");
758 return 0;
759}
760
761static void
762tda998x_encoder_destroy(struct drm_encoder *encoder)
763{
764 struct tda998x_priv *priv = to_tda998x_priv(encoder);
765 drm_i2c_encoder_destroy(encoder);
766 kfree(priv);
767}
768
769static struct drm_encoder_slave_funcs tda998x_encoder_funcs = {
770 .set_config = tda998x_encoder_set_config,
771 .destroy = tda998x_encoder_destroy,
772 .dpms = tda998x_encoder_dpms,
773 .save = tda998x_encoder_save,
774 .restore = tda998x_encoder_restore,
775 .mode_fixup = tda998x_encoder_mode_fixup,
776 .mode_valid = tda998x_encoder_mode_valid,
777 .mode_set = tda998x_encoder_mode_set,
778 .detect = tda998x_encoder_detect,
779 .get_modes = tda998x_encoder_get_modes,
780 .create_resources = tda998x_encoder_create_resources,
781 .set_property = tda998x_encoder_set_property,
782};
783
784/* I2C driver functions */
785
786static int
787tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
788{
789 return 0;
790}
791
792static int
793tda998x_remove(struct i2c_client *client)
794{
795 return 0;
796}
797
798static int
799tda998x_encoder_init(struct i2c_client *client,
800 struct drm_device *dev,
801 struct drm_encoder_slave *encoder_slave)
802{
803 struct drm_encoder *encoder = &encoder_slave->base;
804 struct tda998x_priv *priv;
805
806 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
807 if (!priv)
808 return -ENOMEM;
809
810 priv->current_page = 0;
811 priv->cec = i2c_new_dummy(client->adapter, 0x34);
812 priv->dpms = DRM_MODE_DPMS_OFF;
813
814 encoder_slave->slave_priv = priv;
815 encoder_slave->slave_funcs = &tda998x_encoder_funcs;
816
817 /* wake up the device: */
818 cec_write(encoder, REG_CEC_ENAMODS,
819 CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
820
821 tda998x_reset(encoder);
822
823 /* read version: */
824 priv->rev = reg_read(encoder, REG_VERSION_LSB) |
825 reg_read(encoder, REG_VERSION_MSB) << 8;
826
827 /* mask off feature bits: */
828 priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
829
830 switch (priv->rev) {
831 case TDA9989N2: dev_info(dev->dev, "found TDA9989 n2"); break;
832 case TDA19989: dev_info(dev->dev, "found TDA19989"); break;
833 case TDA19989N2: dev_info(dev->dev, "found TDA19989 n2"); break;
834 case TDA19988: dev_info(dev->dev, "found TDA19988"); break;
835 default:
836 DBG("found unsupported device: %04x", priv->rev);
837 goto fail;
838 }
839
840 /* after reset, enable DDC: */
841 reg_write(encoder, REG_DDC_DISABLE, 0x00);
842
843 /* set clock on DDC channel: */
844 reg_write(encoder, REG_TX3, 39);
845
846 /* if necessary, disable multi-master: */
847 if (priv->rev == TDA19989)
848 reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
849
850 cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL,
851 CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
852
853 return 0;
854
855fail:
856 /* if encoder_init fails, the encoder slave is never registered,
857 * so cleanup here:
858 */
859 if (priv->cec)
860 i2c_unregister_device(priv->cec);
861 kfree(priv);
862 encoder_slave->slave_priv = NULL;
863 encoder_slave->slave_funcs = NULL;
864 return -ENXIO;
865}
866
867static struct i2c_device_id tda998x_ids[] = {
868 { "tda998x", 0 },
869 { }
870};
871MODULE_DEVICE_TABLE(i2c, tda998x_ids);
872
873static struct drm_i2c_encoder_driver tda998x_driver = {
874 .i2c_driver = {
875 .probe = tda998x_probe,
876 .remove = tda998x_remove,
877 .driver = {
878 .name = "tda998x",
879 },
880 .id_table = tda998x_ids,
881 },
882 .encoder_init = tda998x_encoder_init,
883};
884
885/* Module initialization */
886
887static int __init
888tda998x_init(void)
889{
890 DBG("");
891 return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver);
892}
893
894static void __exit
895tda998x_exit(void)
896{
897 DBG("");
898 drm_i2c_encoder_unregister(&tda998x_driver);
899}
900
901MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
902MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
903MODULE_LICENSE("GPL");
904
905module_init(tda998x_init);
906module_exit(tda998x_exit);
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c
index 62e826a139b3..4a69ccdef9b4 100644
--- a/drivers/gpu/drm/nouveau/nv04_tv.c
+++ b/drivers/gpu/drm/nouveau/nv04_tv.c
@@ -184,14 +184,23 @@ static const struct drm_encoder_funcs nv04_tv_funcs = {
184 .destroy = nv04_tv_destroy, 184 .destroy = nv04_tv_destroy,
185}; 185};
186 186
187static const struct drm_encoder_helper_funcs nv04_tv_helper_funcs = {
188 .dpms = nv04_tv_dpms,
189 .save = drm_i2c_encoder_save,
190 .restore = drm_i2c_encoder_restore,
191 .mode_fixup = drm_i2c_encoder_mode_fixup,
192 .prepare = nv04_tv_prepare,
193 .commit = nv04_tv_commit,
194 .mode_set = nv04_tv_mode_set,
195 .detect = drm_i2c_encoder_detect,
196};
197
187int 198int
188nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) 199nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
189{ 200{
190 struct nouveau_encoder *nv_encoder; 201 struct nouveau_encoder *nv_encoder;
191 struct drm_encoder *encoder; 202 struct drm_encoder *encoder;
192 struct drm_device *dev = connector->dev; 203 struct drm_device *dev = connector->dev;
193 struct drm_encoder_helper_funcs *hfuncs;
194 struct drm_encoder_slave_funcs *sfuncs;
195 struct nouveau_drm *drm = nouveau_drm(dev); 204 struct nouveau_drm *drm = nouveau_drm(dev);
196 struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 205 struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
197 struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index); 206 struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index);
@@ -207,17 +216,11 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
207 if (!nv_encoder) 216 if (!nv_encoder)
208 return -ENOMEM; 217 return -ENOMEM;
209 218
210 hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
211 if (!hfuncs) {
212 ret = -ENOMEM;
213 goto fail_free;
214 }
215
216 /* Initialize the common members */ 219 /* Initialize the common members */
217 encoder = to_drm_encoder(nv_encoder); 220 encoder = to_drm_encoder(nv_encoder);
218 221
219 drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC); 222 drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
220 drm_encoder_helper_add(encoder, hfuncs); 223 drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs);
221 224
222 encoder->possible_crtcs = entry->heads; 225 encoder->possible_crtcs = entry->heads;
223 encoder->possible_clones = 0; 226 encoder->possible_clones = 0;
@@ -230,30 +233,14 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry)
230 if (ret < 0) 233 if (ret < 0)
231 goto fail_cleanup; 234 goto fail_cleanup;
232 235
233 /* Fill the function pointers */
234 sfuncs = get_slave_funcs(encoder);
235
236 *hfuncs = (struct drm_encoder_helper_funcs) {
237 .dpms = nv04_tv_dpms,
238 .save = sfuncs->save,
239 .restore = sfuncs->restore,
240 .mode_fixup = sfuncs->mode_fixup,
241 .prepare = nv04_tv_prepare,
242 .commit = nv04_tv_commit,
243 .mode_set = nv04_tv_mode_set,
244 .detect = sfuncs->detect,
245 };
246
247 /* Attach it to the specified connector. */ 236 /* Attach it to the specified connector. */
248 sfuncs->create_resources(encoder, connector); 237 get_slave_funcs(encoder)->create_resources(encoder, connector);
249 drm_mode_connector_attach_encoder(connector, encoder); 238 drm_mode_connector_attach_encoder(connector, encoder);
250 239
251 return 0; 240 return 0;
252 241
253fail_cleanup: 242fail_cleanup:
254 drm_encoder_cleanup(encoder); 243 drm_encoder_cleanup(encoder);
255 kfree(hfuncs);
256fail_free:
257 kfree(nv_encoder); 244 kfree(nv_encoder);
258 return ret; 245 return ret;
259} 246}
diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
new file mode 100644
index 000000000000..ae14fd6ea924
--- /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
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__ */
diff --git a/include/drm/drm_encoder_slave.h b/include/drm/drm_encoder_slave.h
index b0c11a7809bb..8b9cc3671858 100644
--- a/include/drm/drm_encoder_slave.h
+++ b/include/drm/drm_encoder_slave.h
@@ -159,4 +159,24 @@ static inline void drm_i2c_encoder_unregister(struct drm_i2c_encoder_driver *dri
159 159
160void drm_i2c_encoder_destroy(struct drm_encoder *encoder); 160void drm_i2c_encoder_destroy(struct drm_encoder *encoder);
161 161
162
163/*
164 * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
165 */
166
167void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode);
168bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder,
169 const struct drm_display_mode *mode,
170 struct drm_display_mode *adjusted_mode);
171void drm_i2c_encoder_prepare(struct drm_encoder *encoder);
172void drm_i2c_encoder_commit(struct drm_encoder *encoder);
173void drm_i2c_encoder_mode_set(struct drm_encoder *encoder,
174 struct drm_display_mode *mode,
175 struct drm_display_mode *adjusted_mode);
176enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder,
177 struct drm_connector *connector);
178void drm_i2c_encoder_save(struct drm_encoder *encoder);
179void drm_i2c_encoder_restore(struct drm_encoder *encoder);
180
181
162#endif 182#endif
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
index 76c709837543..4a3fc244301c 100644
--- a/include/drm/drm_fb_cma_helper.h
+++ b/include/drm/drm_fb_cma_helper.h
@@ -23,5 +23,10 @@ struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
23struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, 23struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
24 unsigned int plane); 24 unsigned int plane);
25 25
26#ifdef CONFIG_DEBUG_FS
27void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m);
28int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg);
29#endif
30
26#endif 31#endif
27 32
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
index f0f6b1af25ad..63397ced9254 100644
--- a/include/drm/drm_gem_cma_helper.h
+++ b/include/drm/drm_gem_cma_helper.h
@@ -41,4 +41,8 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
41 41
42extern const struct vm_operations_struct drm_gem_cma_vm_ops; 42extern const struct vm_operations_struct drm_gem_cma_vm_ops;
43 43
44#ifdef CONFIG_DEBUG_FS
45void drm_gem_cma_describe(struct drm_gem_cma_object *obj, struct seq_file *m);
46#endif
47
44#endif /* __DRM_GEM_CMA_HELPER_H__ */ 48#endif /* __DRM_GEM_CMA_HELPER_H__ */