1/*
2 * Copyright (C) STMicroelectronics SA 2014
3 * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
4 * License terms:  GNU General Public License (GPL), version 2
5 */
6
7#include <linux/clk.h>
8#include <linux/component.h>
9#include <linux/hdmi.h>
10#include <linux/module.h>
11#include <linux/of_gpio.h>
12#include <linux/platform_device.h>
13#include <linux/reset.h>
14
15#include <drm/drmP.h>
16#include <drm/drm_atomic_helper.h>
17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_edid.h>
19
20#include "sti_hdmi.h"
21#include "sti_hdmi_tx3g4c28phy.h"
22#include "sti_hdmi_tx3g0c55phy.h"
23#include "sti_vtg.h"
24
25#define HDMI_CFG                        0x0000
26#define HDMI_INT_EN                     0x0004
27#define HDMI_INT_STA                    0x0008
28#define HDMI_INT_CLR                    0x000C
29#define HDMI_STA                        0x0010
30#define HDMI_ACTIVE_VID_XMIN            0x0100
31#define HDMI_ACTIVE_VID_XMAX            0x0104
32#define HDMI_ACTIVE_VID_YMIN            0x0108
33#define HDMI_ACTIVE_VID_YMAX            0x010C
34#define HDMI_DFLT_CHL0_DAT              0x0110
35#define HDMI_DFLT_CHL1_DAT              0x0114
36#define HDMI_DFLT_CHL2_DAT              0x0118
37#define HDMI_SW_DI_1_HEAD_WORD          0x0210
38#define HDMI_SW_DI_1_PKT_WORD0          0x0214
39#define HDMI_SW_DI_1_PKT_WORD1          0x0218
40#define HDMI_SW_DI_1_PKT_WORD2          0x021C
41#define HDMI_SW_DI_1_PKT_WORD3          0x0220
42#define HDMI_SW_DI_1_PKT_WORD4          0x0224
43#define HDMI_SW_DI_1_PKT_WORD5          0x0228
44#define HDMI_SW_DI_1_PKT_WORD6          0x022C
45#define HDMI_SW_DI_CFG                  0x0230
46#define HDMI_SW_DI_2_HEAD_WORD          0x0600
47#define HDMI_SW_DI_2_PKT_WORD0          0x0604
48#define HDMI_SW_DI_2_PKT_WORD1          0x0608
49#define HDMI_SW_DI_2_PKT_WORD2          0x060C
50#define HDMI_SW_DI_2_PKT_WORD3          0x0610
51#define HDMI_SW_DI_2_PKT_WORD4          0x0614
52#define HDMI_SW_DI_2_PKT_WORD5          0x0618
53#define HDMI_SW_DI_2_PKT_WORD6          0x061C
54
55#define HDMI_IFRAME_SLOT_AVI            1
56#define HDMI_IFRAME_SLOT_AUDIO          2
57
58#define  XCAT(prefix, x, suffix)        prefix ## x ## suffix
59#define  HDMI_SW_DI_N_HEAD_WORD(x)      XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
60#define  HDMI_SW_DI_N_PKT_WORD0(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD0)
61#define  HDMI_SW_DI_N_PKT_WORD1(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD1)
62#define  HDMI_SW_DI_N_PKT_WORD2(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD2)
63#define  HDMI_SW_DI_N_PKT_WORD3(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD3)
64#define  HDMI_SW_DI_N_PKT_WORD4(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD4)
65#define  HDMI_SW_DI_N_PKT_WORD5(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD5)
66#define  HDMI_SW_DI_N_PKT_WORD6(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD6)
67
68#define HDMI_IFRAME_DISABLED            0x0
69#define HDMI_IFRAME_SINGLE_SHOT         0x1
70#define HDMI_IFRAME_FIELD               0x2
71#define HDMI_IFRAME_FRAME               0x3
72#define HDMI_IFRAME_MASK                0x3
73#define HDMI_IFRAME_CFG_DI_N(x, n)       ((x) << ((n-1)*4)) /* n from 1 to 6 */
74
75#define HDMI_CFG_DEVICE_EN              BIT(0)
76#define HDMI_CFG_HDMI_NOT_DVI           BIT(1)
77#define HDMI_CFG_HDCP_EN                BIT(2)
78#define HDMI_CFG_ESS_NOT_OESS           BIT(3)
79#define HDMI_CFG_H_SYNC_POL_NEG         BIT(4)
80#define HDMI_CFG_SINK_TERM_DET_EN       BIT(5)
81#define HDMI_CFG_V_SYNC_POL_NEG         BIT(6)
82#define HDMI_CFG_422_EN                 BIT(8)
83#define HDMI_CFG_FIFO_OVERRUN_CLR       BIT(12)
84#define HDMI_CFG_FIFO_UNDERRUN_CLR      BIT(13)
85#define HDMI_CFG_SW_RST_EN              BIT(31)
86
87#define HDMI_INT_GLOBAL                 BIT(0)
88#define HDMI_INT_SW_RST                 BIT(1)
89#define HDMI_INT_PIX_CAP                BIT(3)
90#define HDMI_INT_HOT_PLUG               BIT(4)
91#define HDMI_INT_DLL_LCK                BIT(5)
92#define HDMI_INT_NEW_FRAME              BIT(6)
93#define HDMI_INT_GENCTRL_PKT            BIT(7)
94#define HDMI_INT_SINK_TERM_PRESENT      BIT(11)
95
96#define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
97			| HDMI_INT_DLL_LCK \
98			| HDMI_INT_HOT_PLUG \
99			| HDMI_INT_GLOBAL)
100
101#define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
102			| HDMI_INT_GENCTRL_PKT \
103			| HDMI_INT_NEW_FRAME \
104			| HDMI_INT_DLL_LCK \
105			| HDMI_INT_HOT_PLUG \
106			| HDMI_INT_PIX_CAP \
107			| HDMI_INT_SW_RST \
108			| HDMI_INT_GLOBAL)
109
110#define HDMI_STA_SW_RST                 BIT(1)
111
112#define HDMI_INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0)
113#define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
114#define HDMI_INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16)
115
116struct sti_hdmi_connector {
117	struct drm_connector drm_connector;
118	struct drm_encoder *encoder;
119	struct sti_hdmi *hdmi;
120};
121
122#define to_sti_hdmi_connector(x) \
123	container_of(x, struct sti_hdmi_connector, drm_connector)
124
125u32 hdmi_read(struct sti_hdmi *hdmi, int offset)
126{
127	return readl(hdmi->regs + offset);
128}
129
130void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset)
131{
132	writel(val, hdmi->regs + offset);
133}
134
135/**
136 * HDMI interrupt handler threaded
137 *
138 * @irq: irq number
139 * @arg: connector structure
140 */
141static irqreturn_t hdmi_irq_thread(int irq, void *arg)
142{
143	struct sti_hdmi *hdmi = arg;
144
145	/* Hot plug/unplug IRQ */
146	if (hdmi->irq_status & HDMI_INT_HOT_PLUG) {
147		hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
148		if (hdmi->drm_dev)
149			drm_helper_hpd_irq_event(hdmi->drm_dev);
150	}
151
152	/* Sw reset and PLL lock are exclusive so we can use the same
153	 * event to signal them
154	 */
155	if (hdmi->irq_status & (HDMI_INT_SW_RST | HDMI_INT_DLL_LCK)) {
156		hdmi->event_received = true;
157		wake_up_interruptible(&hdmi->wait_event);
158	}
159
160	return IRQ_HANDLED;
161}
162
163/**
164 * HDMI interrupt handler
165 *
166 * @irq: irq number
167 * @arg: connector structure
168 */
169static irqreturn_t hdmi_irq(int irq, void *arg)
170{
171	struct sti_hdmi *hdmi = arg;
172
173	/* read interrupt status */
174	hdmi->irq_status = hdmi_read(hdmi, HDMI_INT_STA);
175
176	/* clear interrupt status */
177	hdmi_write(hdmi, hdmi->irq_status, HDMI_INT_CLR);
178
179	/* force sync bus write */
180	hdmi_read(hdmi, HDMI_INT_STA);
181
182	return IRQ_WAKE_THREAD;
183}
184
185/**
186 * Set hdmi active area depending on the drm display mode selected
187 *
188 * @hdmi: pointer on the hdmi internal structure
189 */
190static void hdmi_active_area(struct sti_hdmi *hdmi)
191{
192	u32 xmin, xmax;
193	u32 ymin, ymax;
194
195	xmin = sti_vtg_get_pixel_number(hdmi->mode, 0);
196	xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay - 1);
197	ymin = sti_vtg_get_line_number(hdmi->mode, 0);
198	ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1);
199
200	hdmi_write(hdmi, xmin, HDMI_ACTIVE_VID_XMIN);
201	hdmi_write(hdmi, xmax, HDMI_ACTIVE_VID_XMAX);
202	hdmi_write(hdmi, ymin, HDMI_ACTIVE_VID_YMIN);
203	hdmi_write(hdmi, ymax, HDMI_ACTIVE_VID_YMAX);
204}
205
206/**
207 * Overall hdmi configuration
208 *
209 * @hdmi: pointer on the hdmi internal structure
210 */
211static void hdmi_config(struct sti_hdmi *hdmi)
212{
213	u32 conf;
214
215	DRM_DEBUG_DRIVER("\n");
216
217	/* Clear overrun and underrun fifo */
218	conf = HDMI_CFG_FIFO_OVERRUN_CLR | HDMI_CFG_FIFO_UNDERRUN_CLR;
219
220	/* Enable HDMI mode not DVI */
221	conf |= HDMI_CFG_HDMI_NOT_DVI | HDMI_CFG_ESS_NOT_OESS;
222
223	/* Enable sink term detection */
224	conf |= HDMI_CFG_SINK_TERM_DET_EN;
225
226	/* Set Hsync polarity */
227	if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
228		DRM_DEBUG_DRIVER("H Sync Negative\n");
229		conf |= HDMI_CFG_H_SYNC_POL_NEG;
230	}
231
232	/* Set Vsync polarity */
233	if (hdmi->mode.flags & DRM_MODE_FLAG_NVSYNC) {
234		DRM_DEBUG_DRIVER("V Sync Negative\n");
235		conf |= HDMI_CFG_V_SYNC_POL_NEG;
236	}
237
238	/* Enable HDMI */
239	conf |= HDMI_CFG_DEVICE_EN;
240
241	hdmi_write(hdmi, conf, HDMI_CFG);
242}
243
244/**
245 * Helper to concatenate infoframe in 32 bits word
246 *
247 * @ptr: pointer on the hdmi internal structure
248 * @data: infoframe to write
249 * @size: size to write
250 */
251static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)
252{
253	unsigned long value = 0;
254	size_t i;
255
256	for (i = size; i > 0; i--)
257		value = (value << 8) | ptr[i - 1];
258
259	return value;
260}
261
262/**
263 * Helper to write info frame
264 *
265 * @hdmi: pointer on the hdmi internal structure
266 * @data: infoframe to write
267 * @size: size to write
268 */
269static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi, const u8 *data)
270{
271	const u8 *ptr = data;
272	u32 val, slot, mode, i;
273	u32 head_offset, pack_offset;
274	size_t size;
275
276	switch (*ptr) {
277	case HDMI_INFOFRAME_TYPE_AVI:
278		slot = HDMI_IFRAME_SLOT_AVI;
279		mode = HDMI_IFRAME_FIELD;
280		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);
281		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);
282		size = HDMI_AVI_INFOFRAME_SIZE;
283		break;
284
285	case HDMI_INFOFRAME_TYPE_AUDIO:
286		slot = HDMI_IFRAME_SLOT_AUDIO;
287		mode = HDMI_IFRAME_FRAME;
288		head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
289		pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
290		size = HDMI_AUDIO_INFOFRAME_SIZE;
291		break;
292
293	default:
294		DRM_ERROR("unsupported infoframe type: %#x\n", *ptr);
295		return;
296	}
297
298	/* Disable transmission slot for updated infoframe */
299	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
300	val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);
301	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
302
303	val = HDMI_INFOFRAME_HEADER_TYPE(*ptr++);
304	val |= HDMI_INFOFRAME_HEADER_VERSION(*ptr++);
305	val |= HDMI_INFOFRAME_HEADER_LEN(*ptr++);
306	writel(val, hdmi->regs + head_offset);
307
308	/*
309	 * Each subpack contains 4 bytes
310	 * The First Bytes of the first subpacket must contain the checksum
311	 * Packet size in increase by one.
312	 */
313	for (i = 0; i < size; i += sizeof(u32)) {
314		size_t num;
315
316		num = min_t(size_t, size - i, sizeof(u32));
317		val = hdmi_infoframe_subpack(ptr, num);
318		ptr += sizeof(u32);
319		writel(val, hdmi->regs + pack_offset + i);
320	}
321
322	/* Enable transmission slot for updated infoframe */
323	val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
324	val |= HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_FIELD, slot);
325	hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
326}
327
328/**
329 * Prepare and configure the AVI infoframe
330 *
331 * AVI infoframe are transmitted at least once per two video field and
332 * contains information about HDMI transmission mode such as color space,
333 * colorimetry, ...
334 *
335 * @hdmi: pointer on the hdmi internal structure
336 *
337 * Return negative value if error occurs
338 */
339static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
340{
341	struct drm_display_mode *mode = &hdmi->mode;
342	struct hdmi_avi_infoframe infoframe;
343	u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
344	int ret;
345
346	DRM_DEBUG_DRIVER("\n");
347
348	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
349	if (ret < 0) {
350		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
351		return ret;
352	}
353
354	/* fixed infoframe configuration not linked to the mode */
355	infoframe.colorspace = HDMI_COLORSPACE_RGB;
356	infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
357	infoframe.colorimetry = HDMI_COLORIMETRY_NONE;
358
359	ret = hdmi_avi_infoframe_pack(&infoframe, buffer, sizeof(buffer));
360	if (ret < 0) {
361		DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
362		return ret;
363	}
364
365	hdmi_infoframe_write_infopack(hdmi, buffer);
366
367	return 0;
368}
369
370/**
371 * Prepare and configure the AUDIO infoframe
372 *
373 * AUDIO infoframe are transmitted once per frame and
374 * contains information about HDMI transmission mode such as audio codec,
375 * sample size, ...
376 *
377 * @hdmi: pointer on the hdmi internal structure
378 *
379 * Return negative value if error occurs
380 */
381static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
382{
383	struct hdmi_audio_infoframe infofame;
384	u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
385	int ret;
386
387	ret = hdmi_audio_infoframe_init(&infofame);
388	if (ret < 0) {
389		DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
390		return ret;
391	}
392
393	infofame.channels = 2;
394
395	ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer));
396	if (ret < 0) {
397		DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
398		return ret;
399	}
400
401	hdmi_infoframe_write_infopack(hdmi, buffer);
402
403	return 0;
404}
405
406/**
407 * Software reset of the hdmi subsystem
408 *
409 * @hdmi: pointer on the hdmi internal structure
410 *
411 */
412#define HDMI_TIMEOUT_SWRESET  100   /*milliseconds */
413static void hdmi_swreset(struct sti_hdmi *hdmi)
414{
415	u32 val;
416
417	DRM_DEBUG_DRIVER("\n");
418
419	/* Enable hdmi_audio clock only during hdmi reset */
420	if (clk_prepare_enable(hdmi->clk_audio))
421		DRM_INFO("Failed to prepare/enable hdmi_audio clk\n");
422
423	/* Sw reset */
424	hdmi->event_received = false;
425
426	val = hdmi_read(hdmi, HDMI_CFG);
427	val |= HDMI_CFG_SW_RST_EN;
428	hdmi_write(hdmi, val, HDMI_CFG);
429
430	/* Wait reset completed */
431	wait_event_interruptible_timeout(hdmi->wait_event,
432					 hdmi->event_received == true,
433					 msecs_to_jiffies
434					 (HDMI_TIMEOUT_SWRESET));
435
436	/*
437	 * HDMI_STA_SW_RST bit is set to '1' when SW_RST bit in HDMI_CFG is
438	 * set to '1' and clk_audio is running.
439	 */
440	if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_SW_RST) == 0)
441		DRM_DEBUG_DRIVER("Warning: HDMI sw reset timeout occurs\n");
442
443	val = hdmi_read(hdmi, HDMI_CFG);
444	val &= ~HDMI_CFG_SW_RST_EN;
445	hdmi_write(hdmi, val, HDMI_CFG);
446
447	/* Disable hdmi_audio clock. Not used anymore for drm purpose */
448	clk_disable_unprepare(hdmi->clk_audio);
449}
450
451static void sti_hdmi_disable(struct drm_bridge *bridge)
452{
453	struct sti_hdmi *hdmi = bridge->driver_private;
454
455	u32 val = hdmi_read(hdmi, HDMI_CFG);
456
457	if (!hdmi->enabled)
458		return;
459
460	DRM_DEBUG_DRIVER("\n");
461
462	/* Disable HDMI */
463	val &= ~HDMI_CFG_DEVICE_EN;
464	hdmi_write(hdmi, val, HDMI_CFG);
465
466	hdmi_write(hdmi, 0xffffffff, HDMI_INT_CLR);
467
468	/* Stop the phy */
469	hdmi->phy_ops->stop(hdmi);
470
471	/* Set the default channel data to be a dark red */
472	hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT);
473	hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL1_DAT);
474	hdmi_write(hdmi, 0x0060, HDMI_DFLT_CHL2_DAT);
475
476	/* Disable/unprepare hdmi clock */
477	clk_disable_unprepare(hdmi->clk_phy);
478	clk_disable_unprepare(hdmi->clk_tmds);
479	clk_disable_unprepare(hdmi->clk_pix);
480
481	hdmi->enabled = false;
482}
483
484static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
485{
486	struct sti_hdmi *hdmi = bridge->driver_private;
487
488	DRM_DEBUG_DRIVER("\n");
489
490	if (hdmi->enabled)
491		return;
492
493	/* Prepare/enable clocks */
494	if (clk_prepare_enable(hdmi->clk_pix))
495		DRM_ERROR("Failed to prepare/enable hdmi_pix clk\n");
496	if (clk_prepare_enable(hdmi->clk_tmds))
497		DRM_ERROR("Failed to prepare/enable hdmi_tmds clk\n");
498	if (clk_prepare_enable(hdmi->clk_phy))
499		DRM_ERROR("Failed to prepare/enable hdmi_rejec_pll clk\n");
500
501	hdmi->enabled = true;
502
503	/* Program hdmi serializer and start phy */
504	if (!hdmi->phy_ops->start(hdmi)) {
505		DRM_ERROR("Unable to start hdmi phy\n");
506		return;
507	}
508
509	/* Program hdmi active area */
510	hdmi_active_area(hdmi);
511
512	/* Enable working interrupts */
513	hdmi_write(hdmi, HDMI_WORKING_INT, HDMI_INT_EN);
514
515	/* Program hdmi config */
516	hdmi_config(hdmi);
517
518	/* Program AVI infoframe */
519	if (hdmi_avi_infoframe_config(hdmi))
520		DRM_ERROR("Unable to configure AVI infoframe\n");
521
522	/* Program AUDIO infoframe */
523	if (hdmi_audio_infoframe_config(hdmi))
524		DRM_ERROR("Unable to configure AUDIO infoframe\n");
525
526	/* Sw reset */
527	hdmi_swreset(hdmi);
528}
529
530static void sti_hdmi_set_mode(struct drm_bridge *bridge,
531		struct drm_display_mode *mode,
532		struct drm_display_mode *adjusted_mode)
533{
534	struct sti_hdmi *hdmi = bridge->driver_private;
535	int ret;
536
537	DRM_DEBUG_DRIVER("\n");
538
539	/* Copy the drm display mode in the connector local structure */
540	memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode));
541
542	/* Update clock framerate according to the selected mode */
543	ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);
544	if (ret < 0) {
545		DRM_ERROR("Cannot set rate (%dHz) for hdmi_pix clk\n",
546			  mode->clock * 1000);
547		return;
548	}
549	ret = clk_set_rate(hdmi->clk_phy, mode->clock * 1000);
550	if (ret < 0) {
551		DRM_ERROR("Cannot set rate (%dHz) for hdmi_rejection_pll clk\n",
552			  mode->clock * 1000);
553		return;
554	}
555}
556
557static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
558{
559	/* do nothing */
560}
561
562static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
563	.pre_enable = sti_hdmi_pre_enable,
564	.enable = sti_hdmi_bridge_nope,
565	.disable = sti_hdmi_disable,
566	.post_disable = sti_hdmi_bridge_nope,
567	.mode_set = sti_hdmi_set_mode,
568};
569
570static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
571{
572	struct sti_hdmi_connector *hdmi_connector
573		= to_sti_hdmi_connector(connector);
574	struct sti_hdmi *hdmi = hdmi_connector->hdmi;
575	struct edid *edid;
576	int count;
577
578	DRM_DEBUG_DRIVER("\n");
579
580	edid = drm_get_edid(connector, hdmi->ddc_adapt);
581	if (!edid)
582		goto fail;
583
584	count = drm_add_edid_modes(connector, edid);
585	drm_mode_connector_update_edid_property(connector, edid);
586
587	kfree(edid);
588	return count;
589
590fail:
591	DRM_ERROR("Can not read HDMI EDID\n");
592	return 0;
593}
594
595#define CLK_TOLERANCE_HZ 50
596
597static int sti_hdmi_connector_mode_valid(struct drm_connector *connector,
598					struct drm_display_mode *mode)
599{
600	int target = mode->clock * 1000;
601	int target_min = target - CLK_TOLERANCE_HZ;
602	int target_max = target + CLK_TOLERANCE_HZ;
603	int result;
604	struct sti_hdmi_connector *hdmi_connector
605		= to_sti_hdmi_connector(connector);
606	struct sti_hdmi *hdmi = hdmi_connector->hdmi;
607
608
609	result = clk_round_rate(hdmi->clk_pix, target);
610
611	DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",
612			 target, result);
613
614	if ((result < target_min) || (result > target_max)) {
615		DRM_DEBUG_DRIVER("hdmi pixclk=%d not supported\n", target);
616		return MODE_BAD;
617	}
618
619	return MODE_OK;
620}
621
622struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
623{
624	struct sti_hdmi_connector *hdmi_connector
625		= to_sti_hdmi_connector(connector);
626
627	/* Best encoder is the one associated during connector creation */
628	return hdmi_connector->encoder;
629}
630
631static struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
632	.get_modes = sti_hdmi_connector_get_modes,
633	.mode_valid = sti_hdmi_connector_mode_valid,
634	.best_encoder = sti_hdmi_best_encoder,
635};
636
637/* get detection status of display device */
638static enum drm_connector_status
639sti_hdmi_connector_detect(struct drm_connector *connector, bool force)
640{
641	struct sti_hdmi_connector *hdmi_connector
642		= to_sti_hdmi_connector(connector);
643	struct sti_hdmi *hdmi = hdmi_connector->hdmi;
644
645	DRM_DEBUG_DRIVER("\n");
646
647	if (hdmi->hpd) {
648		DRM_DEBUG_DRIVER("hdmi cable connected\n");
649		return connector_status_connected;
650	}
651
652	DRM_DEBUG_DRIVER("hdmi cable disconnected\n");
653	return connector_status_disconnected;
654}
655
656static void sti_hdmi_connector_destroy(struct drm_connector *connector)
657{
658	struct sti_hdmi_connector *hdmi_connector
659		= to_sti_hdmi_connector(connector);
660
661	drm_connector_unregister(connector);
662	drm_connector_cleanup(connector);
663	kfree(hdmi_connector);
664}
665
666static struct drm_connector_funcs sti_hdmi_connector_funcs = {
667	.dpms = drm_atomic_helper_connector_dpms,
668	.fill_modes = drm_helper_probe_single_connector_modes,
669	.detect = sti_hdmi_connector_detect,
670	.destroy = sti_hdmi_connector_destroy,
671	.reset = drm_atomic_helper_connector_reset,
672	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
673	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
674};
675
676static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
677{
678	struct drm_encoder *encoder;
679
680	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
681		if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
682			return encoder;
683	}
684
685	return NULL;
686}
687
688static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
689{
690	struct sti_hdmi *hdmi = dev_get_drvdata(dev);
691	struct drm_device *drm_dev = data;
692	struct drm_encoder *encoder;
693	struct sti_hdmi_connector *connector;
694	struct drm_connector *drm_connector;
695	struct drm_bridge *bridge;
696	struct device_node *ddc;
697	int err;
698
699	ddc = of_parse_phandle(dev->of_node, "ddc", 0);
700	if (ddc) {
701		hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc);
702		if (!hdmi->ddc_adapt) {
703			err = -EPROBE_DEFER;
704			of_node_put(ddc);
705			return err;
706		}
707
708		of_node_put(ddc);
709	}
710
711	/* Set the drm device handle */
712	hdmi->drm_dev = drm_dev;
713
714	encoder = sti_hdmi_find_encoder(drm_dev);
715	if (!encoder)
716		goto err_adapt;
717
718	connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
719	if (!connector)
720		goto err_adapt;
721
722
723	connector->hdmi = hdmi;
724
725	bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
726	if (!bridge)
727		goto err_adapt;
728
729	bridge->driver_private = hdmi;
730	bridge->funcs = &sti_hdmi_bridge_funcs;
731	drm_bridge_attach(drm_dev, bridge);
732
733	encoder->bridge = bridge;
734	connector->encoder = encoder;
735
736	drm_connector = (struct drm_connector *)connector;
737
738	drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
739
740	drm_connector_init(drm_dev, drm_connector,
741			&sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
742	drm_connector_helper_add(drm_connector,
743			&sti_hdmi_connector_helper_funcs);
744
745	err = drm_connector_register(drm_connector);
746	if (err)
747		goto err_connector;
748
749	err = drm_mode_connector_attach_encoder(drm_connector, encoder);
750	if (err) {
751		DRM_ERROR("Failed to attach a connector to a encoder\n");
752		goto err_sysfs;
753	}
754
755	/* Enable default interrupts */
756	hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN);
757
758	return 0;
759
760err_sysfs:
761	drm_connector_unregister(drm_connector);
762err_connector:
763	drm_connector_cleanup(drm_connector);
764err_adapt:
765	put_device(&hdmi->ddc_adapt->dev);
766	return -EINVAL;
767}
768
769static void sti_hdmi_unbind(struct device *dev,
770		struct device *master, void *data)
771{
772	/* do nothing */
773}
774
775static const struct component_ops sti_hdmi_ops = {
776	.bind = sti_hdmi_bind,
777	.unbind = sti_hdmi_unbind,
778};
779
780static const struct of_device_id hdmi_of_match[] = {
781	{
782		.compatible = "st,stih416-hdmi",
783		.data = &tx3g0c55phy_ops,
784	}, {
785		.compatible = "st,stih407-hdmi",
786		.data = &tx3g4c28phy_ops,
787	}, {
788		/* end node */
789	}
790};
791MODULE_DEVICE_TABLE(of, hdmi_of_match);
792
793static int sti_hdmi_probe(struct platform_device *pdev)
794{
795	struct device *dev = &pdev->dev;
796	struct sti_hdmi *hdmi;
797	struct device_node *np = dev->of_node;
798	struct resource *res;
799	int ret;
800
801	DRM_INFO("%s\n", __func__);
802
803	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
804	if (!hdmi)
805		return -ENOMEM;
806
807	hdmi->dev = pdev->dev;
808
809	/* Get resources */
810	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
811	if (!res) {
812		DRM_ERROR("Invalid hdmi resource\n");
813		return -ENOMEM;
814	}
815	hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
816	if (!hdmi->regs)
817		return -ENOMEM;
818
819	if (of_device_is_compatible(np, "st,stih416-hdmi")) {
820		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
821						   "syscfg");
822		if (!res) {
823			DRM_ERROR("Invalid syscfg resource\n");
824			return -ENOMEM;
825		}
826		hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
827						    resource_size(res));
828		if (!hdmi->syscfg)
829			return -ENOMEM;
830
831	}
832
833	hdmi->phy_ops = (struct hdmi_phy_ops *)
834		of_match_node(hdmi_of_match, np)->data;
835
836	/* Get clock resources */
837	hdmi->clk_pix = devm_clk_get(dev, "pix");
838	if (IS_ERR(hdmi->clk_pix)) {
839		DRM_ERROR("Cannot get hdmi_pix clock\n");
840		return PTR_ERR(hdmi->clk_pix);
841	}
842
843	hdmi->clk_tmds = devm_clk_get(dev, "tmds");
844	if (IS_ERR(hdmi->clk_tmds)) {
845		DRM_ERROR("Cannot get hdmi_tmds clock\n");
846		return PTR_ERR(hdmi->clk_tmds);
847	}
848
849	hdmi->clk_phy = devm_clk_get(dev, "phy");
850	if (IS_ERR(hdmi->clk_phy)) {
851		DRM_ERROR("Cannot get hdmi_phy clock\n");
852		return PTR_ERR(hdmi->clk_phy);
853	}
854
855	hdmi->clk_audio = devm_clk_get(dev, "audio");
856	if (IS_ERR(hdmi->clk_audio)) {
857		DRM_ERROR("Cannot get hdmi_audio clock\n");
858		return PTR_ERR(hdmi->clk_audio);
859	}
860
861	hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
862
863	init_waitqueue_head(&hdmi->wait_event);
864
865	hdmi->irq = platform_get_irq_byname(pdev, "irq");
866
867	ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,
868			hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
869	if (ret) {
870		DRM_ERROR("Failed to register HDMI interrupt\n");
871		return ret;
872	}
873
874	hdmi->reset = devm_reset_control_get(dev, "hdmi");
875	/* Take hdmi out of reset */
876	if (!IS_ERR(hdmi->reset))
877		reset_control_deassert(hdmi->reset);
878
879	platform_set_drvdata(pdev, hdmi);
880
881	return component_add(&pdev->dev, &sti_hdmi_ops);
882}
883
884static int sti_hdmi_remove(struct platform_device *pdev)
885{
886	struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
887
888	if (hdmi->ddc_adapt)
889		put_device(&hdmi->ddc_adapt->dev);
890
891	component_del(&pdev->dev, &sti_hdmi_ops);
892	return 0;
893}
894
895struct platform_driver sti_hdmi_driver = {
896	.driver = {
897		.name = "sti-hdmi",
898		.owner = THIS_MODULE,
899		.of_match_table = hdmi_of_match,
900	},
901	.probe = sti_hdmi_probe,
902	.remove = sti_hdmi_remove,
903};
904
905module_platform_driver(sti_hdmi_driver);
906
907MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
908MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
909MODULE_LICENSE("GPL");
910