xref: /openbmc/linux/drivers/gpu/drm/sti/sti_tvout.c (revision 7bcae826)
1 /*
2  * Copyright (C) STMicroelectronics SA 2014
3  * Authors: Benjamin Gaignard <benjamin.gaignard@st.com>
4  *          Vincent Abriou <vincent.abriou@st.com>
5  *          for STMicroelectronics.
6  * License terms:  GNU General Public License (GPL), version 2
7  */
8 
9 #include <linux/clk.h>
10 #include <linux/component.h>
11 #include <linux/module.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
14 #include <linux/reset.h>
15 #include <linux/seq_file.h>
16 
17 #include <drm/drmP.h>
18 #include <drm/drm_crtc_helper.h>
19 
20 #include "sti_crtc.h"
21 #include "sti_drv.h"
22 #include "sti_vtg.h"
23 
24 /* glue registers */
25 #define TVO_CSC_MAIN_M0                  0x000
26 #define TVO_CSC_MAIN_M1                  0x004
27 #define TVO_CSC_MAIN_M2                  0x008
28 #define TVO_CSC_MAIN_M3                  0x00c
29 #define TVO_CSC_MAIN_M4                  0x010
30 #define TVO_CSC_MAIN_M5                  0x014
31 #define TVO_CSC_MAIN_M6                  0x018
32 #define TVO_CSC_MAIN_M7                  0x01c
33 #define TVO_MAIN_IN_VID_FORMAT           0x030
34 #define TVO_CSC_AUX_M0                   0x100
35 #define TVO_CSC_AUX_M1                   0x104
36 #define TVO_CSC_AUX_M2                   0x108
37 #define TVO_CSC_AUX_M3                   0x10c
38 #define TVO_CSC_AUX_M4                   0x110
39 #define TVO_CSC_AUX_M5                   0x114
40 #define TVO_CSC_AUX_M6                   0x118
41 #define TVO_CSC_AUX_M7                   0x11c
42 #define TVO_AUX_IN_VID_FORMAT            0x130
43 #define TVO_VIP_HDF                      0x400
44 #define TVO_HD_SYNC_SEL                  0x418
45 #define TVO_HD_DAC_CFG_OFF               0x420
46 #define TVO_VIP_HDMI                     0x500
47 #define TVO_HDMI_FORCE_COLOR_0           0x504
48 #define TVO_HDMI_FORCE_COLOR_1           0x508
49 #define TVO_HDMI_CLIP_VALUE_B_CB         0x50c
50 #define TVO_HDMI_CLIP_VALUE_Y_G          0x510
51 #define TVO_HDMI_CLIP_VALUE_R_CR         0x514
52 #define TVO_HDMI_SYNC_SEL                0x518
53 #define TVO_HDMI_DFV_OBS                 0x540
54 #define TVO_VIP_DVO                      0x600
55 #define TVO_DVO_SYNC_SEL                 0x618
56 #define TVO_DVO_CONFIG                   0x620
57 
58 #define TVO_IN_FMT_SIGNED                BIT(0)
59 #define TVO_SYNC_EXT                     BIT(4)
60 
61 #define TVO_VIP_REORDER_R_SHIFT          24
62 #define TVO_VIP_REORDER_G_SHIFT          20
63 #define TVO_VIP_REORDER_B_SHIFT          16
64 #define TVO_VIP_REORDER_MASK             0x3
65 #define TVO_VIP_REORDER_Y_G_SEL          0
66 #define TVO_VIP_REORDER_CB_B_SEL         1
67 #define TVO_VIP_REORDER_CR_R_SEL         2
68 
69 #define TVO_VIP_CLIP_SHIFT               8
70 #define TVO_VIP_CLIP_MASK                0x7
71 #define TVO_VIP_CLIP_DISABLED            0
72 #define TVO_VIP_CLIP_EAV_SAV             1
73 #define TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y 2
74 #define TVO_VIP_CLIP_LIMITED_RANGE_CB_CR 3
75 #define TVO_VIP_CLIP_PROG_RANGE          4
76 
77 #define TVO_VIP_RND_SHIFT                4
78 #define TVO_VIP_RND_MASK                 0x3
79 #define TVO_VIP_RND_8BIT_ROUNDED         0
80 #define TVO_VIP_RND_10BIT_ROUNDED        1
81 #define TVO_VIP_RND_12BIT_ROUNDED        2
82 
83 #define TVO_VIP_SEL_INPUT_MASK           0xf
84 #define TVO_VIP_SEL_INPUT_MAIN           0x0
85 #define TVO_VIP_SEL_INPUT_AUX            0x8
86 #define TVO_VIP_SEL_INPUT_FORCE_COLOR    0xf
87 #define TVO_VIP_SEL_INPUT_BYPASS_MASK    0x1
88 #define TVO_VIP_SEL_INPUT_BYPASSED       1
89 
90 #define TVO_SYNC_MAIN_VTG_SET_REF        0x00
91 #define TVO_SYNC_AUX_VTG_SET_REF         0x10
92 
93 #define TVO_SYNC_HD_DCS_SHIFT            8
94 
95 #define TVO_SYNC_DVO_PAD_HSYNC_SHIFT     8
96 #define TVO_SYNC_DVO_PAD_VSYNC_SHIFT     16
97 
98 #define ENCODER_CRTC_MASK                (BIT(0) | BIT(1))
99 
100 #define TVO_MIN_HD_HEIGHT                720
101 
102 /* enum listing the supported output data format */
103 enum sti_tvout_video_out_type {
104 	STI_TVOUT_VIDEO_OUT_RGB,
105 	STI_TVOUT_VIDEO_OUT_YUV,
106 };
107 
108 struct sti_tvout {
109 	struct device *dev;
110 	struct drm_device *drm_dev;
111 	void __iomem *regs;
112 	struct reset_control *reset;
113 	struct drm_encoder *hdmi;
114 	struct drm_encoder *hda;
115 	struct drm_encoder *dvo;
116 	bool debugfs_registered;
117 };
118 
119 struct sti_tvout_encoder {
120 	struct drm_encoder encoder;
121 	struct sti_tvout *tvout;
122 };
123 
124 #define to_sti_tvout_encoder(x) \
125 	container_of(x, struct sti_tvout_encoder, encoder)
126 
127 #define to_sti_tvout(x) to_sti_tvout_encoder(x)->tvout
128 
129 /* preformatter conversion matrix */
130 static const u32 rgb_to_ycbcr_601[8] = {
131 	0xF927082E, 0x04C9FEAB, 0x01D30964, 0xFA95FD3D,
132 	0x0000082E, 0x00002000, 0x00002000, 0x00000000
133 };
134 
135 /* 709 RGB to YCbCr */
136 static const u32 rgb_to_ycbcr_709[8] = {
137 	0xF891082F, 0x0367FF40, 0x01280B71, 0xF9B1FE20,
138 	0x0000082F, 0x00002000, 0x00002000, 0x00000000
139 };
140 
141 static u32 tvout_read(struct sti_tvout *tvout, int offset)
142 {
143 	return readl(tvout->regs + offset);
144 }
145 
146 static void tvout_write(struct sti_tvout *tvout, u32 val, int offset)
147 {
148 	writel(val, tvout->regs + offset);
149 }
150 
151 /**
152  * Set the clipping mode of a VIP
153  *
154  * @tvout: tvout structure
155  * @reg: register to set
156  * @cr_r:
157  * @y_g:
158  * @cb_b:
159  */
160 static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg,
161 				      u32 cr_r, u32 y_g, u32 cb_b)
162 {
163 	u32 val = tvout_read(tvout, reg);
164 
165 	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT);
166 	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT);
167 	val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT);
168 	val |= cr_r << TVO_VIP_REORDER_R_SHIFT;
169 	val |= y_g << TVO_VIP_REORDER_G_SHIFT;
170 	val |= cb_b << TVO_VIP_REORDER_B_SHIFT;
171 
172 	tvout_write(tvout, val, reg);
173 }
174 
175 /**
176  * Set the clipping mode of a VIP
177  *
178  * @tvout: tvout structure
179  * @reg: register to set
180  * @range: clipping range
181  */
182 static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, int reg, u32 range)
183 {
184 	u32 val = tvout_read(tvout, reg);
185 
186 	val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT);
187 	val |= range << TVO_VIP_CLIP_SHIFT;
188 	tvout_write(tvout, val, reg);
189 }
190 
191 /**
192  * Set the rounded value of a VIP
193  *
194  * @tvout: tvout structure
195  * @reg: register to set
196  * @rnd: rounded val per component
197  */
198 static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd)
199 {
200 	u32 val = tvout_read(tvout, reg);
201 
202 	val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT);
203 	val |= rnd << TVO_VIP_RND_SHIFT;
204 	tvout_write(tvout, val, reg);
205 }
206 
207 /**
208  * Select the VIP input
209  *
210  * @tvout: tvout structure
211  * @reg: register to set
212  * @main_path: main or auxiliary path
213  * @sel_input: selected_input (main/aux + conv)
214  */
215 static void tvout_vip_set_sel_input(struct sti_tvout *tvout,
216 				    int reg,
217 				    bool main_path,
218 				    enum sti_tvout_video_out_type video_out)
219 {
220 	u32 sel_input;
221 	u32 val = tvout_read(tvout, reg);
222 
223 	if (main_path)
224 		sel_input = TVO_VIP_SEL_INPUT_MAIN;
225 	else
226 		sel_input = TVO_VIP_SEL_INPUT_AUX;
227 
228 	switch (video_out) {
229 	case STI_TVOUT_VIDEO_OUT_RGB:
230 		sel_input |= TVO_VIP_SEL_INPUT_BYPASSED;
231 		break;
232 	case STI_TVOUT_VIDEO_OUT_YUV:
233 		sel_input &= ~TVO_VIP_SEL_INPUT_BYPASSED;
234 		break;
235 	}
236 
237 	/* on stih407 chip the sel_input bypass mode logic is inverted */
238 	sel_input = sel_input ^ TVO_VIP_SEL_INPUT_BYPASS_MASK;
239 
240 	val &= ~TVO_VIP_SEL_INPUT_MASK;
241 	val |= sel_input;
242 	tvout_write(tvout, val, reg);
243 }
244 
245 /**
246  * Select the input video signed or unsigned
247  *
248  * @tvout: tvout structure
249  * @reg: register to set
250  * @in_vid_signed: used video input format
251  */
252 static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout,
253 		int reg, u32 in_vid_fmt)
254 {
255 	u32 val = tvout_read(tvout, reg);
256 
257 	val &= ~TVO_IN_FMT_SIGNED;
258 	val |= in_vid_fmt;
259 	tvout_write(tvout, val, reg);
260 }
261 
262 /**
263  * Set preformatter matrix
264  *
265  * @tvout: tvout structure
266  * @mode: display mode structure
267  */
268 static void tvout_preformatter_set_matrix(struct sti_tvout *tvout,
269 					  struct drm_display_mode *mode)
270 {
271 	unsigned int i;
272 	const u32 *pf_matrix;
273 
274 	if (mode->vdisplay >= TVO_MIN_HD_HEIGHT)
275 		pf_matrix = rgb_to_ycbcr_709;
276 	else
277 		pf_matrix = rgb_to_ycbcr_601;
278 
279 	for (i = 0; i < 8; i++) {
280 		tvout_write(tvout, *(pf_matrix + i),
281 			    TVO_CSC_MAIN_M0 + (i * 4));
282 		tvout_write(tvout, *(pf_matrix + i),
283 			    TVO_CSC_AUX_M0 + (i * 4));
284 	}
285 }
286 
287 /**
288  * Start VIP block for DVO output
289  *
290  * @tvout: pointer on tvout structure
291  * @main_path: true if main path has to be used in the vip configuration
292  *	  else aux path is used.
293  */
294 static void tvout_dvo_start(struct sti_tvout *tvout, bool main_path)
295 {
296 	u32 tvo_in_vid_format;
297 	int val, tmp;
298 
299 	dev_dbg(tvout->dev, "%s\n", __func__);
300 
301 	if (main_path) {
302 		DRM_DEBUG_DRIVER("main vip for DVO\n");
303 		/* Select the input sync for dvo */
304 		tmp = TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_DVO;
305 		val  = tmp << TVO_SYNC_DVO_PAD_VSYNC_SHIFT;
306 		val |= tmp << TVO_SYNC_DVO_PAD_HSYNC_SHIFT;
307 		val |= tmp;
308 		tvout_write(tvout, val, TVO_DVO_SYNC_SEL);
309 		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
310 	} else {
311 		DRM_DEBUG_DRIVER("aux vip for DVO\n");
312 		/* Select the input sync for dvo */
313 		tmp = TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_DVO;
314 		val  = tmp << TVO_SYNC_DVO_PAD_VSYNC_SHIFT;
315 		val |= tmp << TVO_SYNC_DVO_PAD_HSYNC_SHIFT;
316 		val |= tmp;
317 		tvout_write(tvout, val, TVO_DVO_SYNC_SEL);
318 		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
319 	}
320 
321 	/* Set color channel order */
322 	tvout_vip_set_color_order(tvout, TVO_VIP_DVO,
323 				  TVO_VIP_REORDER_CR_R_SEL,
324 				  TVO_VIP_REORDER_Y_G_SEL,
325 				  TVO_VIP_REORDER_CB_B_SEL);
326 
327 	/* Set clipping mode */
328 	tvout_vip_set_clip_mode(tvout, TVO_VIP_DVO, TVO_VIP_CLIP_DISABLED);
329 
330 	/* Set round mode (rounded to 8-bit per component) */
331 	tvout_vip_set_rnd(tvout, TVO_VIP_DVO, TVO_VIP_RND_8BIT_ROUNDED);
332 
333 	/* Set input video format */
334 	tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED);
335 
336 	/* Input selection */
337 	tvout_vip_set_sel_input(tvout, TVO_VIP_DVO, main_path,
338 				STI_TVOUT_VIDEO_OUT_RGB);
339 }
340 
341 /**
342  * Start VIP block for HDMI output
343  *
344  * @tvout: pointer on tvout structure
345  * @main_path: true if main path has to be used in the vip configuration
346  *	  else aux path is used.
347  */
348 static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path)
349 {
350 	u32 tvo_in_vid_format;
351 
352 	dev_dbg(tvout->dev, "%s\n", __func__);
353 
354 	if (main_path) {
355 		DRM_DEBUG_DRIVER("main vip for hdmi\n");
356 		/* select the input sync for hdmi */
357 		tvout_write(tvout,
358 			    TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDMI,
359 			    TVO_HDMI_SYNC_SEL);
360 		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
361 	} else {
362 		DRM_DEBUG_DRIVER("aux vip for hdmi\n");
363 		/* select the input sync for hdmi */
364 		tvout_write(tvout,
365 			    TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDMI,
366 			    TVO_HDMI_SYNC_SEL);
367 		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
368 	}
369 
370 	/* set color channel order */
371 	tvout_vip_set_color_order(tvout, TVO_VIP_HDMI,
372 				  TVO_VIP_REORDER_CR_R_SEL,
373 				  TVO_VIP_REORDER_Y_G_SEL,
374 				  TVO_VIP_REORDER_CB_B_SEL);
375 
376 	/* set clipping mode */
377 	tvout_vip_set_clip_mode(tvout, TVO_VIP_HDMI, TVO_VIP_CLIP_DISABLED);
378 
379 	/* set round mode (rounded to 8-bit per component) */
380 	tvout_vip_set_rnd(tvout, TVO_VIP_HDMI, TVO_VIP_RND_8BIT_ROUNDED);
381 
382 	/* set input video format */
383 	tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED);
384 
385 	/* input selection */
386 	tvout_vip_set_sel_input(tvout, TVO_VIP_HDMI, main_path,
387 				STI_TVOUT_VIDEO_OUT_RGB);
388 }
389 
390 /**
391  * Start HDF VIP and HD DAC
392  *
393  * @tvout: pointer on tvout structure
394  * @main_path: true if main path has to be used in the vip configuration
395  *	  else aux path is used.
396  */
397 static void tvout_hda_start(struct sti_tvout *tvout, bool main_path)
398 {
399 	u32 tvo_in_vid_format;
400 	int val;
401 
402 	dev_dbg(tvout->dev, "%s\n", __func__);
403 
404 	if (main_path) {
405 		DRM_DEBUG_DRIVER("main vip for HDF\n");
406 		/* Select the input sync for HD analog and HD DCS */
407 		val  = TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDDCS;
408 		val  = val << TVO_SYNC_HD_DCS_SHIFT;
409 		val |= TVO_SYNC_MAIN_VTG_SET_REF | VTG_SYNC_ID_HDF;
410 		tvout_write(tvout, val, TVO_HD_SYNC_SEL);
411 		tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT;
412 	} else {
413 		DRM_DEBUG_DRIVER("aux vip for HDF\n");
414 		/* Select the input sync for HD analog and HD DCS */
415 		val  = TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDDCS;
416 		val  = val << TVO_SYNC_HD_DCS_SHIFT;
417 		val |= TVO_SYNC_AUX_VTG_SET_REF | VTG_SYNC_ID_HDF;
418 		tvout_write(tvout, val, TVO_HD_SYNC_SEL);
419 		tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT;
420 	}
421 
422 	/* set color channel order */
423 	tvout_vip_set_color_order(tvout, TVO_VIP_HDF,
424 				  TVO_VIP_REORDER_CR_R_SEL,
425 				  TVO_VIP_REORDER_Y_G_SEL,
426 				  TVO_VIP_REORDER_CB_B_SEL);
427 
428 	/* set clipping mode */
429 	tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_DISABLED);
430 
431 	/* set round mode (rounded to 10-bit per component) */
432 	tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED);
433 
434 	/* Set input video format */
435 	tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, TVO_IN_FMT_SIGNED);
436 
437 	/* Input selection */
438 	tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path,
439 				STI_TVOUT_VIDEO_OUT_YUV);
440 
441 	/* power up HD DAC */
442 	tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF);
443 }
444 
445 #define DBGFS_DUMP(reg) seq_printf(s, "\n  %-25s 0x%08X", #reg, \
446 				   readl(tvout->regs + reg))
447 
448 static void tvout_dbg_vip(struct seq_file *s, int val)
449 {
450 	int r, g, b, tmp, mask;
451 	char *const reorder[] = {"Y_G", "Cb_B", "Cr_R"};
452 	char *const clipping[] = {"No", "EAV/SAV", "Limited range RGB/Y",
453 				  "Limited range Cb/Cr", "decided by register"};
454 	char *const round[] = {"8-bit", "10-bit", "12-bit"};
455 	char *const input_sel[] = {"Main (color matrix enabled)",
456 				   "Main (color matrix by-passed)",
457 				   "", "", "", "", "", "",
458 				   "Aux (color matrix enabled)",
459 				   "Aux (color matrix by-passed)",
460 				   "", "", "", "", "", "Force value"};
461 
462 	seq_puts(s, "\t");
463 	mask = TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT;
464 	r = (val & mask) >> TVO_VIP_REORDER_R_SHIFT;
465 	mask = TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT;
466 	g = (val & mask) >> TVO_VIP_REORDER_G_SHIFT;
467 	mask = TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_B_SHIFT;
468 	b = (val & mask) >> TVO_VIP_REORDER_B_SHIFT;
469 	seq_printf(s, "%-24s %s->%s %s->%s %s->%s\n", "Reorder:",
470 		   reorder[r], reorder[TVO_VIP_REORDER_CR_R_SEL],
471 		   reorder[g], reorder[TVO_VIP_REORDER_Y_G_SEL],
472 		   reorder[b], reorder[TVO_VIP_REORDER_CB_B_SEL]);
473 	seq_puts(s, "\t\t\t\t\t");
474 	mask = TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT;
475 	tmp = (val & mask) >> TVO_VIP_CLIP_SHIFT;
476 	seq_printf(s, "%-24s %s\n", "Clipping:", clipping[tmp]);
477 	seq_puts(s, "\t\t\t\t\t");
478 	mask = TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT;
479 	tmp = (val & mask) >> TVO_VIP_RND_SHIFT;
480 	seq_printf(s, "%-24s input data rounded to %s per component\n",
481 		   "Round:", round[tmp]);
482 	seq_puts(s, "\t\t\t\t\t");
483 	tmp = (val & TVO_VIP_SEL_INPUT_MASK);
484 	seq_printf(s, "%-24s %s", "Input selection:", input_sel[tmp]);
485 }
486 
487 static void tvout_dbg_hd_dac_cfg(struct seq_file *s, int val)
488 {
489 	seq_printf(s, "\t%-24s %s", "HD DAC:",
490 		   val & 1 ? "disabled" : "enabled");
491 }
492 
493 static int tvout_dbg_show(struct seq_file *s, void *data)
494 {
495 	struct drm_info_node *node = s->private;
496 	struct sti_tvout *tvout = (struct sti_tvout *)node->info_ent->data;
497 	struct drm_crtc *crtc;
498 
499 	seq_printf(s, "TVOUT: (vaddr = 0x%p)", tvout->regs);
500 
501 	seq_puts(s, "\n\n  HDMI encoder: ");
502 	crtc = tvout->hdmi->crtc;
503 	if (crtc) {
504 		seq_printf(s, "connected to %s path",
505 			   sti_crtc_is_main(crtc) ? "main" : "aux");
506 		DBGFS_DUMP(TVO_HDMI_SYNC_SEL);
507 		DBGFS_DUMP(TVO_VIP_HDMI);
508 		tvout_dbg_vip(s, readl(tvout->regs + TVO_VIP_HDMI));
509 	} else {
510 		seq_puts(s, "disabled");
511 	}
512 
513 	seq_puts(s, "\n\n  DVO encoder: ");
514 	crtc = tvout->dvo->crtc;
515 	if (crtc) {
516 		seq_printf(s, "connected to %s path",
517 			   sti_crtc_is_main(crtc) ? "main" : "aux");
518 		DBGFS_DUMP(TVO_DVO_SYNC_SEL);
519 		DBGFS_DUMP(TVO_DVO_CONFIG);
520 		DBGFS_DUMP(TVO_VIP_DVO);
521 		tvout_dbg_vip(s, readl(tvout->regs + TVO_VIP_DVO));
522 	} else {
523 		seq_puts(s, "disabled");
524 	}
525 
526 	seq_puts(s, "\n\n  HDA encoder: ");
527 	crtc = tvout->hda->crtc;
528 	if (crtc) {
529 		seq_printf(s, "connected to %s path",
530 			   sti_crtc_is_main(crtc) ? "main" : "aux");
531 		DBGFS_DUMP(TVO_HD_SYNC_SEL);
532 		DBGFS_DUMP(TVO_HD_DAC_CFG_OFF);
533 		tvout_dbg_hd_dac_cfg(s,
534 				     readl(tvout->regs + TVO_HD_DAC_CFG_OFF));
535 		DBGFS_DUMP(TVO_VIP_HDF);
536 		tvout_dbg_vip(s, readl(tvout->regs + TVO_VIP_HDF));
537 	} else {
538 		seq_puts(s, "disabled");
539 	}
540 
541 	seq_puts(s, "\n\n  main path configuration");
542 	DBGFS_DUMP(TVO_CSC_MAIN_M0);
543 	DBGFS_DUMP(TVO_CSC_MAIN_M1);
544 	DBGFS_DUMP(TVO_CSC_MAIN_M2);
545 	DBGFS_DUMP(TVO_CSC_MAIN_M3);
546 	DBGFS_DUMP(TVO_CSC_MAIN_M4);
547 	DBGFS_DUMP(TVO_CSC_MAIN_M5);
548 	DBGFS_DUMP(TVO_CSC_MAIN_M6);
549 	DBGFS_DUMP(TVO_CSC_MAIN_M7);
550 	DBGFS_DUMP(TVO_MAIN_IN_VID_FORMAT);
551 
552 	seq_puts(s, "\n\n  auxiliary path configuration");
553 	DBGFS_DUMP(TVO_CSC_AUX_M0);
554 	DBGFS_DUMP(TVO_CSC_AUX_M2);
555 	DBGFS_DUMP(TVO_CSC_AUX_M3);
556 	DBGFS_DUMP(TVO_CSC_AUX_M4);
557 	DBGFS_DUMP(TVO_CSC_AUX_M5);
558 	DBGFS_DUMP(TVO_CSC_AUX_M6);
559 	DBGFS_DUMP(TVO_CSC_AUX_M7);
560 	DBGFS_DUMP(TVO_AUX_IN_VID_FORMAT);
561 	seq_puts(s, "\n");
562 
563 	return 0;
564 }
565 
566 static struct drm_info_list tvout_debugfs_files[] = {
567 	{ "tvout", tvout_dbg_show, 0, NULL },
568 };
569 
570 static int tvout_debugfs_init(struct sti_tvout *tvout, struct drm_minor *minor)
571 {
572 	unsigned int i;
573 
574 	for (i = 0; i < ARRAY_SIZE(tvout_debugfs_files); i++)
575 		tvout_debugfs_files[i].data = tvout;
576 
577 	return drm_debugfs_create_files(tvout_debugfs_files,
578 					ARRAY_SIZE(tvout_debugfs_files),
579 					minor->debugfs_root, minor);
580 }
581 
582 static void sti_tvout_encoder_dpms(struct drm_encoder *encoder, int mode)
583 {
584 }
585 
586 static void sti_tvout_encoder_mode_set(struct drm_encoder *encoder,
587 				       struct drm_display_mode *mode,
588 				       struct drm_display_mode *adjusted_mode)
589 {
590 }
591 
592 static void sti_tvout_encoder_destroy(struct drm_encoder *encoder)
593 {
594 	struct sti_tvout_encoder *sti_encoder = to_sti_tvout_encoder(encoder);
595 
596 	drm_encoder_cleanup(encoder);
597 	kfree(sti_encoder);
598 }
599 
600 static int sti_tvout_late_register(struct drm_encoder *encoder)
601 {
602 	struct sti_tvout *tvout = to_sti_tvout(encoder);
603 	int ret;
604 
605 	if (tvout->debugfs_registered)
606 		return 0;
607 
608 	ret = tvout_debugfs_init(tvout, encoder->dev->primary);
609 	if (ret)
610 		return ret;
611 
612 	tvout->debugfs_registered = true;
613 	return 0;
614 }
615 
616 static void sti_tvout_early_unregister(struct drm_encoder *encoder)
617 {
618 	struct sti_tvout *tvout = to_sti_tvout(encoder);
619 
620 	if (!tvout->debugfs_registered)
621 		return;
622 
623 	tvout->debugfs_registered = false;
624 }
625 
626 static const struct drm_encoder_funcs sti_tvout_encoder_funcs = {
627 	.destroy = sti_tvout_encoder_destroy,
628 	.late_register = sti_tvout_late_register,
629 	.early_unregister = sti_tvout_early_unregister,
630 };
631 
632 static void sti_dvo_encoder_enable(struct drm_encoder *encoder)
633 {
634 	struct sti_tvout *tvout = to_sti_tvout(encoder);
635 
636 	tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode);
637 
638 	tvout_dvo_start(tvout, sti_crtc_is_main(encoder->crtc));
639 }
640 
641 static void sti_dvo_encoder_disable(struct drm_encoder *encoder)
642 {
643 	struct sti_tvout *tvout = to_sti_tvout(encoder);
644 
645 	/* Reset VIP register */
646 	tvout_write(tvout, 0x0, TVO_VIP_DVO);
647 }
648 
649 static const struct drm_encoder_helper_funcs sti_dvo_encoder_helper_funcs = {
650 	.dpms = sti_tvout_encoder_dpms,
651 	.mode_set = sti_tvout_encoder_mode_set,
652 	.enable = sti_dvo_encoder_enable,
653 	.disable = sti_dvo_encoder_disable,
654 };
655 
656 static struct drm_encoder *
657 sti_tvout_create_dvo_encoder(struct drm_device *dev,
658 			     struct sti_tvout *tvout)
659 {
660 	struct sti_tvout_encoder *encoder;
661 	struct drm_encoder *drm_encoder;
662 
663 	encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
664 	if (!encoder)
665 		return NULL;
666 
667 	encoder->tvout = tvout;
668 
669 	drm_encoder = (struct drm_encoder *)encoder;
670 
671 	drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
672 	drm_encoder->possible_clones = 1 << 0;
673 
674 	drm_encoder_init(dev, drm_encoder,
675 			 &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS,
676 			 NULL);
677 
678 	drm_encoder_helper_add(drm_encoder, &sti_dvo_encoder_helper_funcs);
679 
680 	return drm_encoder;
681 }
682 
683 static void sti_hda_encoder_enable(struct drm_encoder *encoder)
684 {
685 	struct sti_tvout *tvout = to_sti_tvout(encoder);
686 
687 	tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode);
688 
689 	tvout_hda_start(tvout, sti_crtc_is_main(encoder->crtc));
690 }
691 
692 static void sti_hda_encoder_disable(struct drm_encoder *encoder)
693 {
694 	struct sti_tvout *tvout = to_sti_tvout(encoder);
695 
696 	/* reset VIP register */
697 	tvout_write(tvout, 0x0, TVO_VIP_HDF);
698 
699 	/* power down HD DAC */
700 	tvout_write(tvout, 1, TVO_HD_DAC_CFG_OFF);
701 }
702 
703 static const struct drm_encoder_helper_funcs sti_hda_encoder_helper_funcs = {
704 	.dpms = sti_tvout_encoder_dpms,
705 	.mode_set = sti_tvout_encoder_mode_set,
706 	.commit = sti_hda_encoder_enable,
707 	.disable = sti_hda_encoder_disable,
708 };
709 
710 static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev,
711 		struct sti_tvout *tvout)
712 {
713 	struct sti_tvout_encoder *encoder;
714 	struct drm_encoder *drm_encoder;
715 
716 	encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
717 	if (!encoder)
718 		return NULL;
719 
720 	encoder->tvout = tvout;
721 
722 	drm_encoder = (struct drm_encoder *) encoder;
723 
724 	drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
725 	drm_encoder->possible_clones = 1 << 0;
726 
727 	drm_encoder_init(dev, drm_encoder,
728 			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL);
729 
730 	drm_encoder_helper_add(drm_encoder, &sti_hda_encoder_helper_funcs);
731 
732 	return drm_encoder;
733 }
734 
735 static void sti_hdmi_encoder_enable(struct drm_encoder *encoder)
736 {
737 	struct sti_tvout *tvout = to_sti_tvout(encoder);
738 
739 	tvout_preformatter_set_matrix(tvout, &encoder->crtc->mode);
740 
741 	tvout_hdmi_start(tvout, sti_crtc_is_main(encoder->crtc));
742 }
743 
744 static void sti_hdmi_encoder_disable(struct drm_encoder *encoder)
745 {
746 	struct sti_tvout *tvout = to_sti_tvout(encoder);
747 
748 	/* reset VIP register */
749 	tvout_write(tvout, 0x0, TVO_VIP_HDMI);
750 }
751 
752 static const struct drm_encoder_helper_funcs sti_hdmi_encoder_helper_funcs = {
753 	.dpms = sti_tvout_encoder_dpms,
754 	.mode_set = sti_tvout_encoder_mode_set,
755 	.commit = sti_hdmi_encoder_enable,
756 	.disable = sti_hdmi_encoder_disable,
757 };
758 
759 static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev,
760 		struct sti_tvout *tvout)
761 {
762 	struct sti_tvout_encoder *encoder;
763 	struct drm_encoder *drm_encoder;
764 
765 	encoder = devm_kzalloc(tvout->dev, sizeof(*encoder), GFP_KERNEL);
766 	if (!encoder)
767 		return NULL;
768 
769 	encoder->tvout = tvout;
770 
771 	drm_encoder = (struct drm_encoder *) encoder;
772 
773 	drm_encoder->possible_crtcs = ENCODER_CRTC_MASK;
774 	drm_encoder->possible_clones = 1 << 1;
775 
776 	drm_encoder_init(dev, drm_encoder,
777 			&sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL);
778 
779 	drm_encoder_helper_add(drm_encoder, &sti_hdmi_encoder_helper_funcs);
780 
781 	return drm_encoder;
782 }
783 
784 static void sti_tvout_create_encoders(struct drm_device *dev,
785 		struct sti_tvout *tvout)
786 {
787 	tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout);
788 	tvout->hda = sti_tvout_create_hda_encoder(dev, tvout);
789 	tvout->dvo = sti_tvout_create_dvo_encoder(dev, tvout);
790 }
791 
792 static void sti_tvout_destroy_encoders(struct sti_tvout *tvout)
793 {
794 	if (tvout->hdmi)
795 		drm_encoder_cleanup(tvout->hdmi);
796 	tvout->hdmi = NULL;
797 
798 	if (tvout->hda)
799 		drm_encoder_cleanup(tvout->hda);
800 	tvout->hda = NULL;
801 
802 	if (tvout->dvo)
803 		drm_encoder_cleanup(tvout->dvo);
804 	tvout->dvo = NULL;
805 }
806 
807 static int sti_tvout_bind(struct device *dev, struct device *master, void *data)
808 {
809 	struct sti_tvout *tvout = dev_get_drvdata(dev);
810 	struct drm_device *drm_dev = data;
811 
812 	tvout->drm_dev = drm_dev;
813 
814 	sti_tvout_create_encoders(drm_dev, tvout);
815 
816 	return 0;
817 }
818 
819 static void sti_tvout_unbind(struct device *dev, struct device *master,
820 	void *data)
821 {
822 	struct sti_tvout *tvout = dev_get_drvdata(dev);
823 
824 	sti_tvout_destroy_encoders(tvout);
825 }
826 
827 static const struct component_ops sti_tvout_ops = {
828 	.bind	= sti_tvout_bind,
829 	.unbind	= sti_tvout_unbind,
830 };
831 
832 static int sti_tvout_probe(struct platform_device *pdev)
833 {
834 	struct device *dev = &pdev->dev;
835 	struct device_node *node = dev->of_node;
836 	struct sti_tvout *tvout;
837 	struct resource *res;
838 
839 	DRM_INFO("%s\n", __func__);
840 
841 	if (!node)
842 		return -ENODEV;
843 
844 	tvout = devm_kzalloc(dev, sizeof(*tvout), GFP_KERNEL);
845 	if (!tvout)
846 		return -ENOMEM;
847 
848 	tvout->dev = dev;
849 
850 	/* get Memory ressources */
851 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tvout-reg");
852 	if (!res) {
853 		DRM_ERROR("Invalid glue resource\n");
854 		return -ENOMEM;
855 	}
856 	tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
857 	if (!tvout->regs)
858 		return -ENOMEM;
859 
860 	/* get reset resources */
861 	tvout->reset = devm_reset_control_get(dev, "tvout");
862 	/* take tvout out of reset */
863 	if (!IS_ERR(tvout->reset))
864 		reset_control_deassert(tvout->reset);
865 
866 	platform_set_drvdata(pdev, tvout);
867 
868 	return component_add(dev, &sti_tvout_ops);
869 }
870 
871 static int sti_tvout_remove(struct platform_device *pdev)
872 {
873 	component_del(&pdev->dev, &sti_tvout_ops);
874 	return 0;
875 }
876 
877 static const struct of_device_id tvout_of_match[] = {
878 	{ .compatible = "st,stih407-tvout", },
879 	{ /* end node */ }
880 };
881 MODULE_DEVICE_TABLE(of, tvout_of_match);
882 
883 struct platform_driver sti_tvout_driver = {
884 	.driver = {
885 		.name = "sti-tvout",
886 		.owner = THIS_MODULE,
887 		.of_match_table = tvout_of_match,
888 	},
889 	.probe = sti_tvout_probe,
890 	.remove = sti_tvout_remove,
891 };
892 
893 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
894 MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
895 MODULE_LICENSE("GPL");
896