summaryrefslogtreecommitdiffstats
path: root/meta-xilinx-contrib/recipes-kernel/linux/linux-xlnx/v2023.2/0001-drm-xilinx-Add-encoder-for-Digilent-boards.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-xilinx-contrib/recipes-kernel/linux/linux-xlnx/v2023.2/0001-drm-xilinx-Add-encoder-for-Digilent-boards.patch')
-rw-r--r--meta-xilinx-contrib/recipes-kernel/linux/linux-xlnx/v2023.2/0001-drm-xilinx-Add-encoder-for-Digilent-boards.patch305
1 files changed, 305 insertions, 0 deletions
diff --git a/meta-xilinx-contrib/recipes-kernel/linux/linux-xlnx/v2023.2/0001-drm-xilinx-Add-encoder-for-Digilent-boards.patch b/meta-xilinx-contrib/recipes-kernel/linux/linux-xlnx/v2023.2/0001-drm-xilinx-Add-encoder-for-Digilent-boards.patch
new file mode 100644
index 00000000..660bc218
--- /dev/null
+++ b/meta-xilinx-contrib/recipes-kernel/linux/linux-xlnx/v2023.2/0001-drm-xilinx-Add-encoder-for-Digilent-boards.patch
@@ -0,0 +1,305 @@
1From 21cc8144efdaa3cd8dbd7279f87b14fa3432fae4 Mon Sep 17 00:00:00 2001
2From: Jason Wu <jason.wu.misc@gmail.com>
3Date: Sun, 10 Apr 2016 13:14:13 +1000
4Subject: [PATCH 1/3] drm: xilinx: Add encoder for Digilent boards
5
6Add the dglnt_encoder driver that enables DRM support for the VGA and
7HDMI output ports found on many Digilent boards.
8
9Upstream-Status: Pending
10
11Signed-off-by: Sam Bobrowicz <sbobrowicz@digilentinc.com>
12Signed-off-by: Jason Wu <jason.wu.misc@gmail.com>
13---
14 .../bindings/drm/xilinx/dglnt_encoder.txt | 23 +++
15 drivers/gpu/drm/xilinx/Kconfig | 6 +
16 drivers/gpu/drm/xilinx/Makefile | 1 +
17 drivers/gpu/drm/xilinx/dglnt_encoder.c | 217 +++++++++++++++++++++
18 4 files changed, 247 insertions(+)
19 create mode 100644 Documentation/devicetree/bindings/drm/xilinx/dglnt_encoder.txt
20 create mode 100644 drivers/gpu/drm/xilinx/dglnt_encoder.c
21
22diff --git a/Documentation/devicetree/bindings/drm/xilinx/dglnt_encoder.txt b/Documentation/devicetree/bindings/drm/xilinx/dglnt_encoder.txt
23new file mode 100644
24index 0000000..242b24e
25--- /dev/null
26+++ b/Documentation/devicetree/bindings/drm/xilinx/dglnt_encoder.txt
27@@ -0,0 +1,23 @@
28+Device-Tree bindings for Digilent DRM Encoder Slave
29+
30+This driver provides support for VGA and HDMI outputs on Digilent FPGA boards.
31+The VGA or HDMI port must be connected to a Xilinx display pipeline via an
32+axi2vid IP core.
33+
34+Required properties:
35+ - compatible: Should be "digilent,drm-encoder".
36+
37+Optional properties:
38+ - dglnt,edid-i2c: The I2C device connected to the DDC bus on the video
39+ connector. This is used to obtain the supported resolutions
40+ of an attached monitor. If not defined, then a default
41+ set of resolutions is used and the display will initialize
42+ to 720p. Note most VGA connectors on Digilent boards do
43+ not have the DDC bus routed out.
44+
45+Example:
46+
47+ encoder_0: digilent_encoder {
48+ compatible = "digilent,drm-encoder";
49+ dglnt,edid-i2c = <&i2c1>;
50+ };
51diff --git a/drivers/gpu/drm/xilinx/Kconfig b/drivers/gpu/drm/xilinx/Kconfig
52index 57e18a9..d9ecff2 100644
53--- a/drivers/gpu/drm/xilinx/Kconfig
54+++ b/drivers/gpu/drm/xilinx/Kconfig
55@@ -33,6 +33,12 @@ config DRM_XILINX_DP_SUB
56 help
57 DRM driver for Xilinx Display Port Subsystem.
58
59+config DRM_DIGILENT_ENCODER
60+ tristate "Digilent VGA/HDMI DRM Encoder Driver"
61+ depends on DRM_XILINX
62+ help
63+ DRM slave encoder for Video-out on Digilent boards.
64+
65 config DRM_XILINX_DP_SUB_DEBUG_FS
66 bool "Xilinx DRM DPSUB debugfs"
67 depends on DEBUG_FS && DRM_XILINX_DP_SUB
68diff --git a/drivers/gpu/drm/xilinx/Makefile b/drivers/gpu/drm/xilinx/Makefile
69index 19bc154..c2717e40 100644
70--- a/drivers/gpu/drm/xilinx/Makefile
71+++ b/drivers/gpu/drm/xilinx/Makefile
72@@ -7,6 +7,7 @@ xilinx_drm-y := xilinx_drm_crtc.o xilinx_drm_connector.o xilinx_drm_drv.o \
73 xilinx_drm_plane.o
74 xilinx_drm-y += xilinx_cresample.o xilinx_osd.o xilinx_rgb2yuv.o xilinx_vtc.o
75
76+obj-$(CONFIG_DRM_DIGILENT_ENCODER) += dglnt_encoder.o
77 obj-$(CONFIG_DRM_XILINX) += xilinx_drm.o
78 obj-$(CONFIG_DRM_XILINX_DP) += xilinx_drm_dp.o
79 obj-$(CONFIG_DRM_XILINX_DP_SUB) += xilinx_drm_dp_sub.o
80diff --git a/drivers/gpu/drm/xilinx/dglnt_encoder.c b/drivers/gpu/drm/xilinx/dglnt_encoder.c
81new file mode 100644
82index 0000000..cb9fc7d
83--- /dev/null
84+++ b/drivers/gpu/drm/xilinx/dglnt_encoder.c
85@@ -0,0 +1,217 @@
86+/*
87+ * dglnt_encoder.c - DRM slave encoder for Video-out on Digilent boards
88+ *
89+ * Copyright (C) 2015 Digilent
90+ * Author: Sam Bobrowicz <sbobrowicz@digilentinc.com>
91+ *
92+ * Based on udl_encoder.c and udl_connector.c, Copyright (C) 2012 Red Hat.
93+ * Also based on xilinx_drm_dp.c, Copyright (C) 2014 Xilinx, Inc.
94+ *
95+ * This software is licensed under the terms of the GNU General Public
96+ * License version 2, as published by the Free Software Foundation, and
97+ * may be copied, distributed, and modified under those terms.
98+ *
99+ * This program is distributed in the hope that it will be useful,
100+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
101+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102+ * GNU General Public License for more details.
103+ */
104+
105+#include <drm/drmP.h>
106+#include <drm/drm_edid.h>
107+#include <drm/drm_encoder_slave.h>
108+
109+#include <linux/device.h>
110+#include <linux/module.h>
111+#include <linux/err.h>
112+#include <linux/i2c.h>
113+#include <linux/of.h>
114+#include <linux/of_platform.h>
115+#include <linux/platform_device.h>
116+
117+#define DGLNT_ENC_MAX_FREQ 150000
118+#define DGLNT_ENC_MAX_H 1920
119+#define DGLNT_ENC_MAX_V 1080
120+#define DGLNT_ENC_PREF_H 1280
121+#define DGLNT_ENC_PREF_V 720
122+
123+struct dglnt_encoder {
124+ struct drm_encoder *encoder;
125+ struct i2c_adapter *i2c_bus;
126+ bool i2c_present;
127+};
128+
129+static inline struct dglnt_encoder *to_dglnt_encoder(
130+ struct drm_encoder *encoder)
131+{
132+ return to_encoder_slave(encoder)->slave_priv;
133+}
134+
135+static bool dglnt_mode_fixup(struct drm_encoder *encoder,
136+ const struct drm_display_mode *mode,
137+ struct drm_display_mode *adjusted_mode)
138+{
139+ return true;
140+}
141+
142+static void dglnt_encoder_mode_set(struct drm_encoder *encoder,
143+ struct drm_display_mode *mode,
144+ struct drm_display_mode *adjusted_mode)
145+{
146+}
147+
148+static void
149+dglnt_encoder_dpms(struct drm_encoder *encoder, int mode)
150+{
151+}
152+
153+static void dglnt_encoder_save(struct drm_encoder *encoder)
154+{
155+}
156+
157+static void dglnt_encoder_restore(struct drm_encoder *encoder)
158+{
159+}
160+
161+static int dglnt_encoder_mode_valid(struct drm_encoder *encoder,
162+ struct drm_display_mode *mode)
163+{
164+ if (mode &&
165+ !(mode->flags & ((DRM_MODE_FLAG_INTERLACE |
166+ DRM_MODE_FLAG_DBLCLK) | DRM_MODE_FLAG_3D_MASK)) &&
167+ (mode->clock <= DGLNT_ENC_MAX_FREQ) &&
168+ (mode->hdisplay <= DGLNT_ENC_MAX_H) &&
169+ (mode->vdisplay <= DGLNT_ENC_MAX_V))
170+ return MODE_OK;
171+ return MODE_BAD;
172+}
173+
174+static int dglnt_encoder_get_modes(struct drm_encoder *encoder,
175+ struct drm_connector *connector)
176+{
177+ struct dglnt_encoder *dglnt = to_dglnt_encoder(encoder);
178+ struct edid *edid;
179+ int num_modes = 0;
180+
181+ if (dglnt->i2c_present) {
182+ edid = drm_get_edid(connector, dglnt->i2c_bus);
183+ drm_connector_update_edid_property(connector, edid);
184+ if (edid) {
185+ num_modes = drm_add_edid_modes(connector, edid);
186+ kfree(edid);
187+ }
188+ } else {
189+ num_modes = drm_add_modes_noedid(connector, DGLNT_ENC_MAX_H,
190+ DGLNT_ENC_MAX_V);
191+ drm_set_preferred_mode(connector, DGLNT_ENC_PREF_H,
192+ DGLNT_ENC_PREF_V);
193+ }
194+ return num_modes;
195+}
196+
197+static enum drm_connector_status dglnt_encoder_detect(
198+ struct drm_encoder *encoder,
199+ struct drm_connector *connector)
200+{
201+ struct dglnt_encoder *dglnt = to_dglnt_encoder(encoder);
202+
203+ if (dglnt->i2c_present) {
204+ if (drm_probe_ddc(dglnt->i2c_bus))
205+ return connector_status_connected;
206+ return connector_status_disconnected;
207+ } else
208+ return connector_status_unknown;
209+}
210+
211+static struct drm_encoder_slave_funcs dglnt_encoder_slave_funcs = {
212+ .dpms = dglnt_encoder_dpms,
213+ .save = dglnt_encoder_save,
214+ .restore = dglnt_encoder_restore,
215+ .mode_fixup = dglnt_mode_fixup,
216+ .mode_valid = dglnt_encoder_mode_valid,
217+ .mode_set = dglnt_encoder_mode_set,
218+ .detect = dglnt_encoder_detect,
219+ .get_modes = dglnt_encoder_get_modes,
220+};
221+
222+static int dglnt_encoder_encoder_init(struct platform_device *pdev,
223+ struct drm_device *dev,
224+ struct drm_encoder_slave *encoder)
225+{
226+ struct dglnt_encoder *dglnt = platform_get_drvdata(pdev);
227+ struct device_node *sub_node;
228+
229+ encoder->slave_priv = dglnt;
230+ encoder->slave_funcs = &dglnt_encoder_slave_funcs;
231+
232+ dglnt->encoder = &encoder->base;
233+
234+ /* get i2c adapter for edid */
235+ dglnt->i2c_present = false;
236+ sub_node = of_parse_phandle(pdev->dev.of_node, "dglnt,edid-i2c", 0);
237+ if (sub_node) {
238+ dglnt->i2c_bus = of_find_i2c_adapter_by_node(sub_node);
239+ if (!dglnt->i2c_bus)
240+ DRM_INFO("failed to get the edid i2c adapter, using default modes\n");
241+ else
242+ dglnt->i2c_present = true;
243+ of_node_put(sub_node);
244+ }
245+
246+ return 0;
247+}
248+
249+static int dglnt_encoder_probe(struct platform_device *pdev)
250+{
251+ struct dglnt_encoder *dglnt;
252+
253+ dglnt = devm_kzalloc(&pdev->dev, sizeof(*dglnt), GFP_KERNEL);
254+ if (!dglnt)
255+ return -ENOMEM;
256+
257+ platform_set_drvdata(pdev, dglnt);
258+
259+ return 0;
260+}
261+
262+static int dglnt_encoder_remove(struct platform_device *pdev)
263+{
264+ return 0;
265+}
266+
267+static const struct of_device_id dglnt_encoder_of_match[] = {
268+ { .compatible = "digilent,drm-encoder", },
269+ { /* end of table */ },
270+};
271+MODULE_DEVICE_TABLE(of, dglnt_encoder_of_match);
272+
273+static struct drm_platform_encoder_driver dglnt_encoder_driver = {
274+ .platform_driver = {
275+ .probe = dglnt_encoder_probe,
276+ .remove = dglnt_encoder_remove,
277+ .driver = {
278+ .owner = THIS_MODULE,
279+ .name = "dglnt-drm-enc",
280+ .of_match_table = dglnt_encoder_of_match,
281+ },
282+ },
283+
284+ .encoder_init = dglnt_encoder_encoder_init,
285+};
286+
287+static int __init dglnt_encoder_init(void)
288+{
289+ return platform_driver_register(&dglnt_encoder_driver.platform_driver);
290+}
291+
292+static void __exit dglnt_encoder_exit(void)
293+{
294+ platform_driver_unregister(&dglnt_encoder_driver.platform_driver);
295+}
296+
297+module_init(dglnt_encoder_init);
298+module_exit(dglnt_encoder_exit);
299+
300+MODULE_AUTHOR("Digilent, Inc.");
301+MODULE_DESCRIPTION("DRM slave encoder for Video-out on Digilent boards");
302+MODULE_LICENSE("GPL v2");
303--
3042.7.4
305