1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <drm/drmP.h>
21#include <drm/drm_crtc.h>
22#include <drm/drm_crtc_helper.h>
23#include <drm/drm_encoder_slave.h>
24
25#include <linux/hdmi.h>
26#include <linux/err.h>
27#include <linux/i2c.h>
28#include <linux/of.h>
29#include <linux/platform_device.h>
30
31#include "xylon_drv.h"
32#include "xylon_encoder.h"
33
34struct xylon_drm_encoder {
35 struct drm_encoder_slave slave;
36 struct i2c_client *client;
37 int dpms;
38};
39
40#define to_xylon_encoder(x) container_of(x, struct xylon_drm_encoder, slave)
41
42static void xylon_drm_encoder_dpms(struct drm_encoder *base_encoder, int dpms)
43{
44 struct xylon_drm_encoder *encoder;
45 struct drm_encoder_slave *encoder_slave;
46 struct drm_encoder_slave_funcs *encoder_sfuncs;
47
48 encoder_slave = to_encoder_slave(base_encoder);
49 encoder_sfuncs = encoder_slave->slave_funcs;
50 encoder = to_xylon_encoder(encoder_slave);
51
52 if (encoder->dpms == dpms)
53 return;
54
55 encoder->dpms = dpms;
56 if (encoder_sfuncs->dpms)
57 encoder_sfuncs->dpms(base_encoder, dpms);
58}
59
60static bool
61xylon_drm_encoder_mode_fixup(struct drm_encoder *base_encoder,
62 const struct drm_display_mode *mode,
63 struct drm_display_mode *adjusted_mode)
64{
65 struct drm_encoder_slave *encoder_slave;
66 struct drm_encoder_slave_funcs *encoder_sfuncs;
67 bool ret = true;
68
69 encoder_slave = to_encoder_slave(base_encoder);
70 encoder_sfuncs = encoder_slave->slave_funcs;
71 if (encoder_sfuncs->mode_fixup)
72 ret = encoder_sfuncs->mode_fixup(base_encoder, mode,
73 adjusted_mode);
74
75 return ret;
76}
77
78static void xylon_drm_encoder_mode_set(struct drm_encoder *base_encoder,
79 struct drm_display_mode *mode,
80 struct drm_display_mode *adjusted_mode)
81{
82 struct xylon_drm_encoder *encoder;
83 struct drm_device *dev = base_encoder->dev;
84 struct drm_encoder_slave *encoder_slave;
85 struct drm_encoder_slave_funcs *encoder_sfuncs;
86 struct drm_connector *iter;
87 struct drm_connector *connector = NULL;
88
89 DRM_DEBUG("h: %d, v: %d\n",
90 adjusted_mode->hdisplay, adjusted_mode->vdisplay);
91 DRM_DEBUG("refresh: %d, pclock: %d khz\n",
92 adjusted_mode->vrefresh, adjusted_mode->clock);
93
94 encoder_slave = to_encoder_slave(base_encoder);
95 encoder = to_xylon_encoder(encoder_slave);
96
97 list_for_each_entry(iter, &dev->mode_config.connector_list, head) {
98 if (iter->encoder == base_encoder) {
99 connector = iter;
100 break;
101 }
102 }
103 if (!connector) {
104 DRM_ERROR("failed find a connector\n");
105 return;
106 }
107
108 encoder_sfuncs = encoder_slave->slave_funcs;
109 if (encoder_sfuncs->mode_set)
110 encoder_sfuncs->mode_set(base_encoder, mode, adjusted_mode);
111}
112
113static void xylon_drm_encoder_commit(struct drm_encoder *base_encoder)
114{
115 xylon_drm_encoder_dpms(base_encoder, DRM_MODE_DPMS_ON);
116}
117
118static void xylon_drm_encoder_prepare(struct drm_encoder *base_encoder)
119{
120 xylon_drm_encoder_dpms(base_encoder, DRM_MODE_DPMS_OFF);
121}
122
123static struct drm_crtc *
124xylon_drm_encoder_get_crtc(struct drm_encoder *base_encoder)
125{
126 return base_encoder->crtc;
127}
128
129static struct drm_encoder_helper_funcs xylon_drm_encoder_helper_funcs = {
130 .dpms = xylon_drm_encoder_dpms,
131 .mode_fixup = xylon_drm_encoder_mode_fixup,
132 .mode_set = xylon_drm_encoder_mode_set,
133 .prepare = xylon_drm_encoder_prepare,
134 .commit = xylon_drm_encoder_commit,
135 .get_crtc = xylon_drm_encoder_get_crtc,
136};
137
138static void xylon_drm_encoder_destroy(struct drm_encoder *base_encoder)
139{
140 struct xylon_drm_encoder *encoder;
141 struct drm_encoder_slave *encoder_slave;
142
143 encoder_slave = to_encoder_slave(base_encoder);
144 encoder = to_xylon_encoder(encoder_slave);
145
146 xylon_drm_encoder_dpms(base_encoder, DRM_MODE_DPMS_OFF);
147
148 drm_encoder_cleanup(base_encoder);
149 put_device(&encoder->client->dev);
150}
151
152static struct drm_encoder_funcs xylon_drm_encoder_funcs = {
153 .destroy = xylon_drm_encoder_destroy,
154};
155
156struct drm_encoder *xylon_drm_encoder_create(struct drm_device *dev)
157{
158 struct xylon_drm_encoder *encoder;
159 struct device_node *sub_node;
160 struct i2c_driver *i2c_driver;
161 struct drm_i2c_encoder_driver *drm_i2c_driver;
162 int ret;
163
164 encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
165 if (!encoder)
166 return ERR_PTR(-ENOMEM);
167
168 encoder->dpms = DRM_MODE_DPMS_OFF;
169
170 encoder->slave.base.possible_crtcs = 1;
171 ret = drm_encoder_init(dev, &encoder->slave.base,
172 &xylon_drm_encoder_funcs,
173 DRM_MODE_ENCODER_TMDS);
174 if (ret) {
175 DRM_ERROR("failed initialize encoder\n");
176 return ERR_PTR(ret);
177 }
178
179 drm_encoder_helper_add(&encoder->slave.base,
180 &xylon_drm_encoder_helper_funcs);
181
182 sub_node = of_parse_phandle(dev->dev->of_node, "encoder", 0);
183 if (!sub_node) {
184 DRM_ERROR("failed get encoder\n");
185 return ERR_PTR(-ENODEV);
186 }
187
188 encoder->client = of_find_i2c_device_by_node(sub_node);
189 of_node_put(sub_node);
190 if (!encoder->client || !encoder->client->dev.driver) {
191 DRM_INFO("failed find encoder\n");
192 return ERR_PTR(-EPROBE_DEFER);
193 }
194
195 i2c_driver = to_i2c_driver(encoder->client->dev.driver);
196 drm_i2c_driver = to_drm_i2c_encoder_driver(i2c_driver);
197 if (!drm_i2c_driver) {
198 DRM_ERROR("failed initialize encoder driver\n");
199 return ERR_PTR(-EPROBE_DEFER);
200 }
201
202 ret = drm_i2c_driver->encoder_init(encoder->client, dev,
203 &encoder->slave);
204 if (ret) {
205 DRM_ERROR("failed initialize encoder\n");
206 return ERR_PTR(ret);
207 }
208
209 if (!encoder->slave.slave_funcs) {
210 DRM_ERROR("failed check encoder function\n");
211 return ERR_PTR(-ENODEV);
212 }
213
214 return &encoder->slave.base;
215}
216