1 /*
2  * Copyright (C) 2016 Maxime Ripard
3  *
4  * Maxime Ripard <maxime.ripard@free-electrons.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of
9  * the License, or (at your option) any later version.
10  */
11 
12 #include <drm/drmP.h>
13 #include <drm/drm_atomic_helper.h>
14 #include <drm/drm_crtc_helper.h>
15 #include <drm/drm_edid.h>
16 #include <drm/drm_encoder.h>
17 #include <drm/drm_of.h>
18 #include <drm/drm_panel.h>
19 
20 #include <linux/clk.h>
21 #include <linux/component.h>
22 #include <linux/iopoll.h>
23 #include <linux/of_device.h>
24 #include <linux/platform_device.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/regmap.h>
27 #include <linux/reset.h>
28 
29 #include "sun4i_backend.h"
30 #include "sun4i_crtc.h"
31 #include "sun4i_drv.h"
32 #include "sun4i_hdmi.h"
33 
34 static inline struct sun4i_hdmi *
35 drm_encoder_to_sun4i_hdmi(struct drm_encoder *encoder)
36 {
37 	return container_of(encoder, struct sun4i_hdmi,
38 			    encoder);
39 }
40 
41 static inline struct sun4i_hdmi *
42 drm_connector_to_sun4i_hdmi(struct drm_connector *connector)
43 {
44 	return container_of(connector, struct sun4i_hdmi,
45 			    connector);
46 }
47 
48 static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
49 					   struct drm_display_mode *mode)
50 {
51 	struct hdmi_avi_infoframe frame;
52 	u8 buffer[17];
53 	int i, ret;
54 
55 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
56 	if (ret < 0) {
57 		DRM_ERROR("Failed to get infoframes from mode\n");
58 		return ret;
59 	}
60 
61 	ret = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
62 	if (ret < 0) {
63 		DRM_ERROR("Failed to pack infoframes\n");
64 		return ret;
65 	}
66 
67 	for (i = 0; i < sizeof(buffer); i++)
68 		writeb(buffer[i], hdmi->base + SUN4I_HDMI_AVI_INFOFRAME_REG(i));
69 
70 	return 0;
71 }
72 
73 static int sun4i_hdmi_atomic_check(struct drm_encoder *encoder,
74 				   struct drm_crtc_state *crtc_state,
75 				   struct drm_connector_state *conn_state)
76 {
77 	struct drm_display_mode *mode = &crtc_state->mode;
78 
79 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
80 		return -EINVAL;
81 
82 	return 0;
83 }
84 
85 static void sun4i_hdmi_disable(struct drm_encoder *encoder)
86 {
87 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
88 	u32 val;
89 
90 	DRM_DEBUG_DRIVER("Disabling the HDMI Output\n");
91 
92 	val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
93 	val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
94 	writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
95 }
96 
97 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
98 {
99 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
100 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
101 	u32 val = 0;
102 
103 	DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
104 
105 	sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
106 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
107 	val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
108 	writel(val, hdmi->base + SUN4I_HDMI_PKT_CTRL_REG(0));
109 
110 	val = SUN4I_HDMI_VID_CTRL_ENABLE;
111 	if (hdmi->hdmi_monitor)
112 		val |= SUN4I_HDMI_VID_CTRL_HDMI_MODE;
113 
114 	writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
115 }
116 
117 static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
118 				struct drm_display_mode *mode,
119 				struct drm_display_mode *adjusted_mode)
120 {
121 	struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
122 	unsigned int x, y;
123 	u32 val;
124 
125 	clk_set_rate(hdmi->mod_clk, mode->crtc_clock * 1000);
126 	clk_set_rate(hdmi->tmds_clk, mode->crtc_clock * 1000);
127 
128 	/* Set input sync enable */
129 	writel(SUN4I_HDMI_UNKNOWN_INPUT_SYNC,
130 	       hdmi->base + SUN4I_HDMI_UNKNOWN_REG);
131 
132 	/*
133 	 * Setup output pad (?) controls
134 	 *
135 	 * This is done here instead of at probe/bind time because
136 	 * the controller seems to toggle some of the bits on its own.
137 	 *
138 	 * We can't just initialize the register there, we need to
139 	 * protect the clock bits that have already been read out and
140 	 * cached by the clock framework.
141 	 */
142 	val = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
143 	val &= SUN4I_HDMI_PAD_CTRL1_HALVE_CLK;
144 	val |= hdmi->variant->pad_ctrl1_init_val;
145 	writel(val, hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
146 	val = readl(hdmi->base + SUN4I_HDMI_PAD_CTRL1_REG);
147 
148 	/* Setup timing registers */
149 	writel(SUN4I_HDMI_VID_TIMING_X(mode->hdisplay) |
150 	       SUN4I_HDMI_VID_TIMING_Y(mode->vdisplay),
151 	       hdmi->base + SUN4I_HDMI_VID_TIMING_ACT_REG);
152 
153 	x = mode->htotal - mode->hsync_start;
154 	y = mode->vtotal - mode->vsync_start;
155 	writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
156 	       hdmi->base + SUN4I_HDMI_VID_TIMING_BP_REG);
157 
158 	x = mode->hsync_start - mode->hdisplay;
159 	y = mode->vsync_start - mode->vdisplay;
160 	writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
161 	       hdmi->base + SUN4I_HDMI_VID_TIMING_FP_REG);
162 
163 	x = mode->hsync_end - mode->hsync_start;
164 	y = mode->vsync_end - mode->vsync_start;
165 	writel(SUN4I_HDMI_VID_TIMING_X(x) | SUN4I_HDMI_VID_TIMING_Y(y),
166 	       hdmi->base + SUN4I_HDMI_VID_TIMING_SPW_REG);
167 
168 	val = SUN4I_HDMI_VID_TIMING_POL_TX_CLK;
169 	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
170 		val |= SUN4I_HDMI_VID_TIMING_POL_HSYNC;
171 
172 	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
173 		val |= SUN4I_HDMI_VID_TIMING_POL_VSYNC;
174 
175 	writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
176 }
177 
178 static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
179 	.atomic_check	= sun4i_hdmi_atomic_check,
180 	.disable	= sun4i_hdmi_disable,
181 	.enable		= sun4i_hdmi_enable,
182 	.mode_set	= sun4i_hdmi_mode_set,
183 };
184 
185 static const struct drm_encoder_funcs sun4i_hdmi_funcs = {
186 	.destroy	= drm_encoder_cleanup,
187 };
188 
189 static int sun4i_hdmi_get_modes(struct drm_connector *connector)
190 {
191 	struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
192 	struct edid *edid;
193 	int ret;
194 
195 	edid = drm_get_edid(connector, hdmi->i2c);
196 	if (!edid)
197 		return 0;
198 
199 	hdmi->hdmi_monitor = drm_detect_hdmi_monitor(edid);
200 	DRM_DEBUG_DRIVER("Monitor is %s monitor\n",
201 			 hdmi->hdmi_monitor ? "an HDMI" : "a DVI");
202 
203 	drm_mode_connector_update_edid_property(connector, edid);
204 	cec_s_phys_addr_from_edid(hdmi->cec_adap, edid);
205 	ret = drm_add_edid_modes(connector, edid);
206 	kfree(edid);
207 
208 	return ret;
209 }
210 
211 static const struct drm_connector_helper_funcs sun4i_hdmi_connector_helper_funcs = {
212 	.get_modes	= sun4i_hdmi_get_modes,
213 };
214 
215 static enum drm_connector_status
216 sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force)
217 {
218 	struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
219 	unsigned long reg;
220 
221 	if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_HPD_REG, reg,
222 			       reg & SUN4I_HDMI_HPD_HIGH,
223 			       0, 500000)) {
224 		cec_phys_addr_invalidate(hdmi->cec_adap);
225 		return connector_status_disconnected;
226 	}
227 
228 	return connector_status_connected;
229 }
230 
231 static const struct drm_connector_funcs sun4i_hdmi_connector_funcs = {
232 	.detect			= sun4i_hdmi_connector_detect,
233 	.fill_modes		= drm_helper_probe_single_connector_modes,
234 	.destroy		= drm_connector_cleanup,
235 	.reset			= drm_atomic_helper_connector_reset,
236 	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
237 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
238 };
239 
240 #ifdef CONFIG_DRM_SUN4I_HDMI_CEC
241 static bool sun4i_hdmi_cec_pin_read(struct cec_adapter *adap)
242 {
243 	struct sun4i_hdmi *hdmi = cec_get_drvdata(adap);
244 
245 	return readl(hdmi->base + SUN4I_HDMI_CEC) & SUN4I_HDMI_CEC_RX;
246 }
247 
248 static void sun4i_hdmi_cec_pin_low(struct cec_adapter *adap)
249 {
250 	struct sun4i_hdmi *hdmi = cec_get_drvdata(adap);
251 
252 	/* Start driving the CEC pin low */
253 	writel(SUN4I_HDMI_CEC_ENABLE, hdmi->base + SUN4I_HDMI_CEC);
254 }
255 
256 static void sun4i_hdmi_cec_pin_high(struct cec_adapter *adap)
257 {
258 	struct sun4i_hdmi *hdmi = cec_get_drvdata(adap);
259 
260 	/*
261 	 * Stop driving the CEC pin, the pull up will take over
262 	 * unless another CEC device is driving the pin low.
263 	 */
264 	writel(0, hdmi->base + SUN4I_HDMI_CEC);
265 }
266 
267 static const struct cec_pin_ops sun4i_hdmi_cec_pin_ops = {
268 	.read = sun4i_hdmi_cec_pin_read,
269 	.low = sun4i_hdmi_cec_pin_low,
270 	.high = sun4i_hdmi_cec_pin_high,
271 };
272 #endif
273 
274 #define SUN4I_HDMI_PAD_CTRL1_MASK	(GENMASK(24, 7) | GENMASK(5, 0))
275 #define SUN4I_HDMI_PLL_CTRL_MASK	(GENMASK(31, 8) | GENMASK(3, 0))
276 
277 /* Only difference from sun5i is AMP is 4 instead of 6 */
278 static const struct sun4i_hdmi_variant sun4i_variant = {
279 	.pad_ctrl0_init_val	= SUN4I_HDMI_PAD_CTRL0_TXEN |
280 				  SUN4I_HDMI_PAD_CTRL0_CKEN |
281 				  SUN4I_HDMI_PAD_CTRL0_PWENG |
282 				  SUN4I_HDMI_PAD_CTRL0_PWEND |
283 				  SUN4I_HDMI_PAD_CTRL0_PWENC |
284 				  SUN4I_HDMI_PAD_CTRL0_LDODEN |
285 				  SUN4I_HDMI_PAD_CTRL0_LDOCEN |
286 				  SUN4I_HDMI_PAD_CTRL0_BIASEN,
287 	.pad_ctrl1_init_val	= SUN4I_HDMI_PAD_CTRL1_REG_AMP(4) |
288 				  SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) |
289 				  SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
290 				  SUN4I_HDMI_PAD_CTRL1_REG_DEN |
291 				  SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
292 				  SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
293 				  SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
294 				  SUN4I_HDMI_PAD_CTRL1_AMP_OPT,
295 	.pll_ctrl_init_val	= SUN4I_HDMI_PLL_CTRL_VCO_S(8) |
296 				  SUN4I_HDMI_PLL_CTRL_CS(7) |
297 				  SUN4I_HDMI_PLL_CTRL_CP_S(15) |
298 				  SUN4I_HDMI_PLL_CTRL_S(7) |
299 				  SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) |
300 				  SUN4I_HDMI_PLL_CTRL_SDIV2 |
301 				  SUN4I_HDMI_PLL_CTRL_LDO2_EN |
302 				  SUN4I_HDMI_PLL_CTRL_LDO1_EN |
303 				  SUN4I_HDMI_PLL_CTRL_HV_IS_33 |
304 				  SUN4I_HDMI_PLL_CTRL_BWS |
305 				  SUN4I_HDMI_PLL_CTRL_PLL_EN,
306 
307 	.ddc_clk_reg		= REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6),
308 	.ddc_clk_pre_divider	= 2,
309 	.ddc_clk_m_offset	= 1,
310 
311 	.field_ddc_en		= REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31),
312 	.field_ddc_start	= REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30),
313 	.field_ddc_reset	= REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0),
314 	.field_ddc_addr_reg	= REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31),
315 	.field_ddc_slave_addr	= REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6),
316 	.field_ddc_int_status	= REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8),
317 	.field_ddc_fifo_clear	= REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31),
318 	.field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7),
319 	.field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3),
320 	.field_ddc_byte_count	= REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9),
321 	.field_ddc_cmd		= REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2),
322 	.field_ddc_sda_en	= REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9),
323 	.field_ddc_sck_en	= REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8),
324 
325 	.ddc_fifo_reg		= SUN4I_HDMI_DDC_FIFO_DATA_REG,
326 	.ddc_fifo_has_dir	= true,
327 };
328 
329 static const struct sun4i_hdmi_variant sun5i_variant = {
330 	.pad_ctrl0_init_val	= SUN4I_HDMI_PAD_CTRL0_TXEN |
331 				  SUN4I_HDMI_PAD_CTRL0_CKEN |
332 				  SUN4I_HDMI_PAD_CTRL0_PWENG |
333 				  SUN4I_HDMI_PAD_CTRL0_PWEND |
334 				  SUN4I_HDMI_PAD_CTRL0_PWENC |
335 				  SUN4I_HDMI_PAD_CTRL0_LDODEN |
336 				  SUN4I_HDMI_PAD_CTRL0_LDOCEN |
337 				  SUN4I_HDMI_PAD_CTRL0_BIASEN,
338 	.pad_ctrl1_init_val	= SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) |
339 				  SUN4I_HDMI_PAD_CTRL1_REG_EMP(2) |
340 				  SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
341 				  SUN4I_HDMI_PAD_CTRL1_REG_DEN |
342 				  SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
343 				  SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
344 				  SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
345 				  SUN4I_HDMI_PAD_CTRL1_AMP_OPT,
346 	.pll_ctrl_init_val	= SUN4I_HDMI_PLL_CTRL_VCO_S(8) |
347 				  SUN4I_HDMI_PLL_CTRL_CS(7) |
348 				  SUN4I_HDMI_PLL_CTRL_CP_S(15) |
349 				  SUN4I_HDMI_PLL_CTRL_S(7) |
350 				  SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) |
351 				  SUN4I_HDMI_PLL_CTRL_SDIV2 |
352 				  SUN4I_HDMI_PLL_CTRL_LDO2_EN |
353 				  SUN4I_HDMI_PLL_CTRL_LDO1_EN |
354 				  SUN4I_HDMI_PLL_CTRL_HV_IS_33 |
355 				  SUN4I_HDMI_PLL_CTRL_BWS |
356 				  SUN4I_HDMI_PLL_CTRL_PLL_EN,
357 
358 	.ddc_clk_reg		= REG_FIELD(SUN4I_HDMI_DDC_CLK_REG, 0, 6),
359 	.ddc_clk_pre_divider	= 2,
360 	.ddc_clk_m_offset	= 1,
361 
362 	.field_ddc_en		= REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 31, 31),
363 	.field_ddc_start	= REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 30, 30),
364 	.field_ddc_reset	= REG_FIELD(SUN4I_HDMI_DDC_CTRL_REG, 0, 0),
365 	.field_ddc_addr_reg	= REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 31),
366 	.field_ddc_slave_addr	= REG_FIELD(SUN4I_HDMI_DDC_ADDR_REG, 0, 6),
367 	.field_ddc_int_status	= REG_FIELD(SUN4I_HDMI_DDC_INT_STATUS_REG, 0, 8),
368 	.field_ddc_fifo_clear	= REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 31, 31),
369 	.field_ddc_fifo_rx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 4, 7),
370 	.field_ddc_fifo_tx_thres = REG_FIELD(SUN4I_HDMI_DDC_FIFO_CTRL_REG, 0, 3),
371 	.field_ddc_byte_count	= REG_FIELD(SUN4I_HDMI_DDC_BYTE_COUNT_REG, 0, 9),
372 	.field_ddc_cmd		= REG_FIELD(SUN4I_HDMI_DDC_CMD_REG, 0, 2),
373 	.field_ddc_sda_en	= REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 9, 9),
374 	.field_ddc_sck_en	= REG_FIELD(SUN4I_HDMI_DDC_LINE_CTRL_REG, 8, 8),
375 
376 	.ddc_fifo_reg		= SUN4I_HDMI_DDC_FIFO_DATA_REG,
377 	.ddc_fifo_has_dir	= true,
378 };
379 
380 static const struct sun4i_hdmi_variant sun6i_variant = {
381 	.has_ddc_parent_clk	= true,
382 	.has_reset_control	= true,
383 	.pad_ctrl0_init_val	= 0xff |
384 				  SUN4I_HDMI_PAD_CTRL0_TXEN |
385 				  SUN4I_HDMI_PAD_CTRL0_CKEN |
386 				  SUN4I_HDMI_PAD_CTRL0_PWENG |
387 				  SUN4I_HDMI_PAD_CTRL0_PWEND |
388 				  SUN4I_HDMI_PAD_CTRL0_PWENC |
389 				  SUN4I_HDMI_PAD_CTRL0_LDODEN |
390 				  SUN4I_HDMI_PAD_CTRL0_LDOCEN,
391 	.pad_ctrl1_init_val	= SUN4I_HDMI_PAD_CTRL1_REG_AMP(6) |
392 				  SUN4I_HDMI_PAD_CTRL1_REG_EMP(4) |
393 				  SUN4I_HDMI_PAD_CTRL1_REG_DENCK |
394 				  SUN4I_HDMI_PAD_CTRL1_REG_DEN |
395 				  SUN4I_HDMI_PAD_CTRL1_EMPCK_OPT |
396 				  SUN4I_HDMI_PAD_CTRL1_EMP_OPT |
397 				  SUN4I_HDMI_PAD_CTRL1_PWSDT |
398 				  SUN4I_HDMI_PAD_CTRL1_PWSCK |
399 				  SUN4I_HDMI_PAD_CTRL1_AMPCK_OPT |
400 				  SUN4I_HDMI_PAD_CTRL1_AMP_OPT |
401 				  SUN4I_HDMI_PAD_CTRL1_UNKNOWN,
402 	.pll_ctrl_init_val	= SUN4I_HDMI_PLL_CTRL_VCO_S(8) |
403 				  SUN4I_HDMI_PLL_CTRL_CS(3) |
404 				  SUN4I_HDMI_PLL_CTRL_CP_S(10) |
405 				  SUN4I_HDMI_PLL_CTRL_S(4) |
406 				  SUN4I_HDMI_PLL_CTRL_VCO_GAIN(4) |
407 				  SUN4I_HDMI_PLL_CTRL_SDIV2 |
408 				  SUN4I_HDMI_PLL_CTRL_LDO2_EN |
409 				  SUN4I_HDMI_PLL_CTRL_LDO1_EN |
410 				  SUN4I_HDMI_PLL_CTRL_HV_IS_33 |
411 				  SUN4I_HDMI_PLL_CTRL_PLL_EN,
412 
413 	.ddc_clk_reg		= REG_FIELD(SUN6I_HDMI_DDC_CLK_REG, 0, 6),
414 	.ddc_clk_pre_divider	= 1,
415 	.ddc_clk_m_offset	= 2,
416 
417 	.tmds_clk_div_offset	= 1,
418 
419 	.field_ddc_en		= REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 0, 0),
420 	.field_ddc_start	= REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 27, 27),
421 	.field_ddc_reset	= REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 31, 31),
422 	.field_ddc_addr_reg	= REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 31),
423 	.field_ddc_slave_addr	= REG_FIELD(SUN6I_HDMI_DDC_ADDR_REG, 1, 7),
424 	.field_ddc_int_status	= REG_FIELD(SUN6I_HDMI_DDC_INT_STATUS_REG, 0, 8),
425 	.field_ddc_fifo_clear	= REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 18, 18),
426 	.field_ddc_fifo_rx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 4, 7),
427 	.field_ddc_fifo_tx_thres = REG_FIELD(SUN6I_HDMI_DDC_FIFO_CTRL_REG, 0, 3),
428 	.field_ddc_byte_count	= REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 16, 25),
429 	.field_ddc_cmd		= REG_FIELD(SUN6I_HDMI_DDC_CMD_REG, 0, 2),
430 	.field_ddc_sda_en	= REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 6, 6),
431 	.field_ddc_sck_en	= REG_FIELD(SUN6I_HDMI_DDC_CTRL_REG, 4, 4),
432 
433 	.ddc_fifo_reg		= SUN6I_HDMI_DDC_FIFO_DATA_REG,
434 	.ddc_fifo_thres_incl	= true,
435 };
436 
437 static const struct regmap_config sun4i_hdmi_regmap_config = {
438 	.reg_bits	= 32,
439 	.val_bits	= 32,
440 	.reg_stride	= 4,
441 	.max_register	= 0x580,
442 };
443 
444 static int sun4i_hdmi_bind(struct device *dev, struct device *master,
445 			   void *data)
446 {
447 	struct platform_device *pdev = to_platform_device(dev);
448 	struct drm_device *drm = data;
449 	struct sun4i_drv *drv = drm->dev_private;
450 	struct sun4i_hdmi *hdmi;
451 	struct resource *res;
452 	u32 reg;
453 	int ret;
454 
455 	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
456 	if (!hdmi)
457 		return -ENOMEM;
458 	dev_set_drvdata(dev, hdmi);
459 	hdmi->dev = dev;
460 	hdmi->drv = drv;
461 
462 	hdmi->variant = of_device_get_match_data(dev);
463 	if (!hdmi->variant)
464 		return -EINVAL;
465 
466 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
467 	hdmi->base = devm_ioremap_resource(dev, res);
468 	if (IS_ERR(hdmi->base)) {
469 		dev_err(dev, "Couldn't map the HDMI encoder registers\n");
470 		return PTR_ERR(hdmi->base);
471 	}
472 
473 	if (hdmi->variant->has_reset_control) {
474 		hdmi->reset = devm_reset_control_get(dev, NULL);
475 		if (IS_ERR(hdmi->reset)) {
476 			dev_err(dev, "Couldn't get the HDMI reset control\n");
477 			return PTR_ERR(hdmi->reset);
478 		}
479 
480 		ret = reset_control_deassert(hdmi->reset);
481 		if (ret) {
482 			dev_err(dev, "Couldn't deassert HDMI reset\n");
483 			return ret;
484 		}
485 	}
486 
487 	hdmi->bus_clk = devm_clk_get(dev, "ahb");
488 	if (IS_ERR(hdmi->bus_clk)) {
489 		dev_err(dev, "Couldn't get the HDMI bus clock\n");
490 		ret = PTR_ERR(hdmi->bus_clk);
491 		goto err_assert_reset;
492 	}
493 	clk_prepare_enable(hdmi->bus_clk);
494 
495 	hdmi->mod_clk = devm_clk_get(dev, "mod");
496 	if (IS_ERR(hdmi->mod_clk)) {
497 		dev_err(dev, "Couldn't get the HDMI mod clock\n");
498 		ret = PTR_ERR(hdmi->mod_clk);
499 		goto err_disable_bus_clk;
500 	}
501 	clk_prepare_enable(hdmi->mod_clk);
502 
503 	hdmi->pll0_clk = devm_clk_get(dev, "pll-0");
504 	if (IS_ERR(hdmi->pll0_clk)) {
505 		dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n");
506 		ret = PTR_ERR(hdmi->pll0_clk);
507 		goto err_disable_mod_clk;
508 	}
509 
510 	hdmi->pll1_clk = devm_clk_get(dev, "pll-1");
511 	if (IS_ERR(hdmi->pll1_clk)) {
512 		dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n");
513 		ret = PTR_ERR(hdmi->pll1_clk);
514 		goto err_disable_mod_clk;
515 	}
516 
517 	hdmi->regmap = devm_regmap_init_mmio(dev, hdmi->base,
518 					     &sun4i_hdmi_regmap_config);
519 	if (IS_ERR(hdmi->regmap)) {
520 		dev_err(dev, "Couldn't create HDMI encoder regmap\n");
521 		return PTR_ERR(hdmi->regmap);
522 	}
523 
524 	ret = sun4i_tmds_create(hdmi);
525 	if (ret) {
526 		dev_err(dev, "Couldn't create the TMDS clock\n");
527 		goto err_disable_mod_clk;
528 	}
529 
530 	if (hdmi->variant->has_ddc_parent_clk) {
531 		hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc");
532 		if (IS_ERR(hdmi->ddc_parent_clk)) {
533 			dev_err(dev, "Couldn't get the HDMI DDC clock\n");
534 			return PTR_ERR(hdmi->ddc_parent_clk);
535 		}
536 	} else {
537 		hdmi->ddc_parent_clk = hdmi->tmds_clk;
538 	}
539 
540 	writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG);
541 
542 	writel(hdmi->variant->pad_ctrl0_init_val,
543 	       hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG);
544 
545 	reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
546 	reg &= SUN4I_HDMI_PLL_CTRL_DIV_MASK;
547 	reg |= hdmi->variant->pll_ctrl_init_val;
548 	writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
549 
550 	ret = sun4i_hdmi_i2c_create(dev, hdmi);
551 	if (ret) {
552 		dev_err(dev, "Couldn't create the HDMI I2C adapter\n");
553 		goto err_disable_mod_clk;
554 	}
555 
556 	drm_encoder_helper_add(&hdmi->encoder,
557 			       &sun4i_hdmi_helper_funcs);
558 	ret = drm_encoder_init(drm,
559 			       &hdmi->encoder,
560 			       &sun4i_hdmi_funcs,
561 			       DRM_MODE_ENCODER_TMDS,
562 			       NULL);
563 	if (ret) {
564 		dev_err(dev, "Couldn't initialise the HDMI encoder\n");
565 		goto err_del_i2c_adapter;
566 	}
567 
568 	hdmi->encoder.possible_crtcs = drm_of_find_possible_crtcs(drm,
569 								  dev->of_node);
570 	if (!hdmi->encoder.possible_crtcs) {
571 		ret = -EPROBE_DEFER;
572 		goto err_del_i2c_adapter;
573 	}
574 
575 #ifdef CONFIG_DRM_SUN4I_HDMI_CEC
576 	hdmi->cec_adap = cec_pin_allocate_adapter(&sun4i_hdmi_cec_pin_ops,
577 		hdmi, "sun4i", CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
578 		CEC_CAP_PASSTHROUGH | CEC_CAP_RC);
579 	ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
580 	if (ret < 0)
581 		goto err_cleanup_connector;
582 	writel(readl(hdmi->base + SUN4I_HDMI_CEC) & ~SUN4I_HDMI_CEC_TX,
583 	       hdmi->base + SUN4I_HDMI_CEC);
584 #endif
585 
586 	drm_connector_helper_add(&hdmi->connector,
587 				 &sun4i_hdmi_connector_helper_funcs);
588 	ret = drm_connector_init(drm, &hdmi->connector,
589 				 &sun4i_hdmi_connector_funcs,
590 				 DRM_MODE_CONNECTOR_HDMIA);
591 	if (ret) {
592 		dev_err(dev,
593 			"Couldn't initialise the HDMI connector\n");
594 		goto err_cleanup_connector;
595 	}
596 
597 	/* There is no HPD interrupt, so we need to poll the controller */
598 	hdmi->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
599 		DRM_CONNECTOR_POLL_DISCONNECT;
600 
601 	ret = cec_register_adapter(hdmi->cec_adap, dev);
602 	if (ret < 0)
603 		goto err_cleanup_connector;
604 	drm_mode_connector_attach_encoder(&hdmi->connector, &hdmi->encoder);
605 
606 	return 0;
607 
608 err_cleanup_connector:
609 	cec_delete_adapter(hdmi->cec_adap);
610 	drm_encoder_cleanup(&hdmi->encoder);
611 err_del_i2c_adapter:
612 	i2c_del_adapter(hdmi->i2c);
613 err_disable_mod_clk:
614 	clk_disable_unprepare(hdmi->mod_clk);
615 err_disable_bus_clk:
616 	clk_disable_unprepare(hdmi->bus_clk);
617 err_assert_reset:
618 	reset_control_assert(hdmi->reset);
619 	return ret;
620 }
621 
622 static void sun4i_hdmi_unbind(struct device *dev, struct device *master,
623 			    void *data)
624 {
625 	struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
626 
627 	cec_unregister_adapter(hdmi->cec_adap);
628 	drm_connector_cleanup(&hdmi->connector);
629 	drm_encoder_cleanup(&hdmi->encoder);
630 	i2c_del_adapter(hdmi->i2c);
631 	clk_disable_unprepare(hdmi->mod_clk);
632 	clk_disable_unprepare(hdmi->bus_clk);
633 }
634 
635 static const struct component_ops sun4i_hdmi_ops = {
636 	.bind	= sun4i_hdmi_bind,
637 	.unbind	= sun4i_hdmi_unbind,
638 };
639 
640 static int sun4i_hdmi_probe(struct platform_device *pdev)
641 {
642 	return component_add(&pdev->dev, &sun4i_hdmi_ops);
643 }
644 
645 static int sun4i_hdmi_remove(struct platform_device *pdev)
646 {
647 	component_del(&pdev->dev, &sun4i_hdmi_ops);
648 
649 	return 0;
650 }
651 
652 static const struct of_device_id sun4i_hdmi_of_table[] = {
653 	{ .compatible = "allwinner,sun4i-a10-hdmi", .data = &sun4i_variant, },
654 	{ .compatible = "allwinner,sun5i-a10s-hdmi", .data = &sun5i_variant, },
655 	{ .compatible = "allwinner,sun6i-a31-hdmi", .data = &sun6i_variant, },
656 	{ }
657 };
658 MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table);
659 
660 static struct platform_driver sun4i_hdmi_driver = {
661 	.probe		= sun4i_hdmi_probe,
662 	.remove		= sun4i_hdmi_remove,
663 	.driver		= {
664 		.name		= "sun4i-hdmi",
665 		.of_match_table	= sun4i_hdmi_of_table,
666 	},
667 };
668 module_platform_driver(sun4i_hdmi_driver);
669 
670 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
671 MODULE_DESCRIPTION("Allwinner A10 HDMI Driver");
672 MODULE_LICENSE("GPL");
673