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