upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / samsung / tvout / s5p_tvif_ctrl.c
1 /* linux/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
2  *
3  * Copyright (c) 2009 Samsung Electronics
4  *              http://www.samsung.com/
5  *
6  * Tvout ctrl class for Samsung TVOUT driver
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 /*****************************************************************************
14  * This file includes functions for ctrl classes of TVOUT driver.
15  * There are 3 ctrl classes. (tvif, hdmi, sdo)
16  *      - tvif ctrl class: controls hdmi and sdo ctrl class.
17  *      - hdmi ctrl class: contrls hdmi hardware by using hw_if/hdmi.c
18  *      - sdo  ctrl class: contrls sdo hardware by using hw_if/sdo.c
19  *
20  *                      +-----------------+
21  *                      | tvif ctrl class |
22  *                      +-----------------+
23  *                             |   |
24  *                  +----------+   +----------+             ctrl class layer
25  *                  |                         |
26  *                  V                         V
27  *         +-----------------+       +-----------------+
28  *         | sdo ctrl class  |       | hdmi ctrl class |
29  *         +-----------------+       +-----------------+
30  *                  |                         |
31  *   ---------------+-------------------------+------------------------------
32  *                  V                         V
33  *         +-----------------+       +-----------------+
34  *         |   hw_if/sdo.c   |       |   hw_if/hdmi.c  |         hw_if layer
35  *         +-----------------+       +-----------------+
36  *                  |                         |
37  *   ---------------+-------------------------+------------------------------
38  *                  V                         V
39  *         +-----------------+       +-----------------+
40  *         |   sdo hardware  |       |   hdmi hardware |          Hardware
41  *         +-----------------+       +-----------------+
42  *
43  ****************************************************************************/
44 #include <linux/clk.h>
45 #include <linux/delay.h>
46 #include <linux/err.h>
47
48 #ifdef CONFIG_CPU_S5PV210
49 #include <mach/pd.h>
50 #endif
51
52 #include "s5p_tvout_common_lib.h"
53 #include "hw_if/hw_if.h"
54 #include "s5p_tvout_ctrl.h"
55
56 /****************************************
57  * Definitions for sdo ctrl class
58  ***************************************/
59 enum {
60         SDO_PCLK = 0,
61         SDO_MUX,
62         SDO_NO_OF_CLK
63 };
64
65 struct s5p_sdo_vscale_cfg {
66         enum s5p_sdo_level              composite_level;
67         enum s5p_sdo_vsync_ratio        composite_ratio;
68 };
69
70 struct s5p_sdo_vbi {
71         bool wss_cvbs;
72         enum s5p_sdo_closed_caption_type caption_cvbs;
73 };
74
75 struct s5p_sdo_offset_gain {
76         u32 offset;
77         u32 gain;
78 };
79
80 struct s5p_sdo_delay {
81         u32 delay_y;
82         u32 offset_video_start;
83         u32 offset_video_end;
84 };
85
86 struct s5p_sdo_component_porch {
87         u32 back_525;
88         u32 front_525;
89         u32 back_625;
90         u32 front_625;
91 };
92
93 struct s5p_sdo_ch_xtalk_cancellat_coeff {
94         u32 coeff1;
95         u32 coeff2;
96 };
97
98 struct s5p_sdo_closed_caption {
99         u32 display_cc;
100         u32 nondisplay_cc;
101 };
102
103 struct s5p_sdo_ctrl_private_data {
104         struct s5p_sdo_vscale_cfg               video_scale_cfg;
105         struct s5p_sdo_vbi                      vbi;
106         struct s5p_sdo_offset_gain              offset_gain;
107         struct s5p_sdo_delay                    delay;
108         struct s5p_sdo_bright_hue_saturation    bri_hue_sat;
109         struct s5p_sdo_cvbs_compensation        cvbs_compen;
110         struct s5p_sdo_component_porch          compo_porch;
111         struct s5p_sdo_ch_xtalk_cancellat_coeff xtalk_cc;
112         struct s5p_sdo_closed_caption           closed_cap;
113         struct s5p_sdo_525_data                 wss_525;
114         struct s5p_sdo_625_data                 wss_625;
115         struct s5p_sdo_525_data                 cgms_525;
116         struct s5p_sdo_625_data                 cgms_625;
117
118         bool                    color_sub_carrier_phase_adj;
119
120         bool                    running;
121
122         struct s5p_tvout_clk_info       clk[SDO_NO_OF_CLK];
123         char                    *pow_name;
124         struct reg_mem_info     reg_mem;
125 };
126
127 static struct s5p_sdo_ctrl_private_data s5p_sdo_ctrl_private = {
128         .clk[SDO_PCLK] = {
129                 .name                   = "tvenc",
130                 .ptr                    = NULL
131         },
132         .clk[SDO_MUX] = {
133                 .name                   = "sclk_dac",
134                 .ptr                    = NULL
135         },
136                 .pow_name               = "tv_enc_pd",
137         .reg_mem = {
138                 .name                   = "s5p-sdo",
139                 .res                    = NULL,
140                 .base                   = NULL
141         },
142
143         .running                        = false,
144
145         .color_sub_carrier_phase_adj    = false,
146
147         .vbi = {
148                 .wss_cvbs               = true,
149                 .caption_cvbs           = SDO_INS_OTHERS
150         },
151
152         .offset_gain = {
153                 .offset                 = 0,
154                 .gain                   = 0x800
155         },
156
157         .delay = {
158                 .delay_y                = 0x00,
159                 .offset_video_start     = 0xfa,
160                 .offset_video_end       = 0x00
161         },
162
163         .bri_hue_sat = {
164                 .bright_hue_sat_adj     = false,
165                 .gain_brightness        = 0x80,
166                 .offset_brightness      = 0x00,
167                 .gain0_cb_hue_sat       = 0x00,
168                 .gain1_cb_hue_sat       = 0x00,
169                 .gain0_cr_hue_sat       = 0x00,
170                 .gain1_cr_hue_sat       = 0x00,
171                 .offset_cb_hue_sat      = 0x00,
172                 .offset_cr_hue_sat      = 0x00
173         },
174
175         .cvbs_compen = {
176                 .cvbs_color_compen      = false,
177                 .y_lower_mid            = 0x200,
178                 .y_bottom               = 0x000,
179                 .y_top                  = 0x3ff,
180                 .y_upper_mid            = 0x200,
181                 .radius                 = 0x1ff
182         },
183
184         .compo_porch = {
185                 .back_525               = 0x8a,
186                 .front_525              = 0x359,
187                 .back_625               = 0x96,
188                 .front_625              = 0x35c
189         },
190
191         .xtalk_cc = {
192                 .coeff2                 = 0,
193                 .coeff1                 = 0
194         },
195
196         .closed_cap = {
197                 .display_cc             = 0,
198                 .nondisplay_cc          = 0
199         },
200
201         .wss_525 = {
202                 .copy_permit            = SDO_525_COPY_PERMIT,
203                 .mv_psp                 = SDO_525_MV_PSP_OFF,
204                 .copy_info              = SDO_525_COPY_INFO,
205                 .analog_on              = false,
206                 .display_ratio          = SDO_525_4_3_NORMAL
207         },
208
209         .wss_625 = {
210                 .surround_sound         = false,
211                 .copyright              = false,
212                 .copy_protection        = false,
213                 .text_subtitles         = false,
214                 .open_subtitles         = SDO_625_NO_OPEN_SUBTITLES,
215                 .camera_film            = SDO_625_CAMERA,
216                 .color_encoding         = SDO_625_NORMAL_PAL,
217                 .helper_signal          = false,
218                 .display_ratio          = SDO_625_4_3_FULL_576
219         },
220
221         .cgms_525 = {
222                 .copy_permit            = SDO_525_COPY_PERMIT,
223                 .mv_psp                 = SDO_525_MV_PSP_OFF,
224                 .copy_info              = SDO_525_COPY_INFO,
225                 .analog_on              = false,
226                 .display_ratio          = SDO_525_4_3_NORMAL
227         },
228
229         .cgms_625 = {
230                 .surround_sound         = false,
231                 .copyright              = false,
232                 .copy_protection        = false,
233                 .text_subtitles         = false,
234                 .open_subtitles         = SDO_625_NO_OPEN_SUBTITLES,
235                 .camera_film            = SDO_625_CAMERA,
236                 .color_encoding         = SDO_625_NORMAL_PAL,
237                 .helper_signal          = false,
238                 .display_ratio          = SDO_625_4_3_FULL_576
239         },
240 };
241
242
243
244
245
246 /****************************************
247  * Definitions for hdmi ctrl class
248  ***************************************/
249
250 #define AVI_SAME_WITH_PICTURE_AR        (0x1<<3)
251
252 enum {
253         HDMI_PCLK = 0,
254         HDMI_MUX,
255         HDMI_NO_OF_CLK
256 };
257
258 enum {
259         HDMI = 0,
260         HDMI_PHY,
261         HDMI_NO_OF_MEM_RES
262 };
263
264 enum s5p_hdmi_pic_aspect {
265         HDMI_PIC_RATIO_4_3      = 1,
266         HDMI_PIC_RATIO_16_9     = 2
267 };
268
269 enum s5p_hdmi_colorimetry {
270         HDMI_CLRIMETRY_NO       = 0x00,
271         HDMI_CLRIMETRY_601      = 0x40,
272         HDMI_CLRIMETRY_709      = 0x80,
273         HDMI_CLRIMETRY_X_VAL    = 0xc0,
274 };
275
276 enum s5p_hdmi_audio_type {
277         HDMI_GENERIC_AUDIO,
278         HDMI_60958_AUDIO,
279         HDMI_DVD_AUDIO,
280         HDMI_SUPER_AUDIO,
281 };
282
283 enum s5p_hdmi_v_mode {
284         v640x480p_60Hz,
285         v720x480p_60Hz,
286         v1280x720p_60Hz,
287         v1920x1080i_60Hz,
288         v720x480i_60Hz,
289         v720x240p_60Hz,
290         v2880x480i_60Hz,
291         v2880x240p_60Hz,
292         v1440x480p_60Hz,
293         v1920x1080p_60Hz,
294         v720x576p_50Hz,
295         v1280x720p_50Hz,
296         v1920x1080i_50Hz,
297         v720x576i_50Hz,
298         v720x288p_50Hz,
299         v2880x576i_50Hz,
300         v2880x288p_50Hz,
301         v1440x576p_50Hz,
302         v1920x1080p_50Hz,
303         v1920x1080p_24Hz,
304         v1920x1080p_25Hz,
305         v1920x1080p_30Hz,
306         v2880x480p_60Hz,
307         v2880x576p_50Hz,
308         v1920x1080i_50Hz_1250,
309         v1920x1080i_100Hz,
310         v1280x720p_100Hz,
311         v720x576p_100Hz,
312         v720x576i_100Hz,
313         v1920x1080i_120Hz,
314         v1280x720p_120Hz,
315         v720x480p_120Hz,
316         v720x480i_120Hz,
317         v720x576p_200Hz,
318         v720x576i_200Hz,
319         v720x480p_240Hz,
320         v720x480i_240Hz,
321         v720x480p_59Hz,
322         v1280x720p_59Hz,
323         v1920x1080i_59Hz,
324         v1920x1080p_59Hz,
325 };
326
327 struct s5p_hdmi_bluescreen {
328         bool    enable;
329         u8      cb_b;
330         u8      y_g;
331         u8      cr_r;
332 };
333
334 struct s5p_hdmi_packet {
335         u8                              acr[7];
336         u8                              asp[7];
337         u8                              gcp[7];
338         u8                              acp[28];
339         u8                              isrc1[16];
340         u8                              isrc2[16];
341         u8                              obas[7];
342         u8                              dst[28];
343         u8                              gmp[28];
344
345         u8                              spd_vendor[8];
346         u8                              spd_product[16];
347
348         u8                              vsi[27];
349         u8                              avi[27];
350         u8                              spd[27];
351         u8                              aui[27];
352         u8                              mpg[27];
353
354         struct s5p_hdmi_infoframe       vsi_info;
355         struct s5p_hdmi_infoframe       avi_info;
356         struct s5p_hdmi_infoframe       spd_info;
357         struct s5p_hdmi_infoframe       aui_info;
358         struct s5p_hdmi_infoframe       mpg_info;
359
360         u8                              h_asp[3];
361         u8                              h_acp[3];
362         u8                              h_isrc[3];
363 };
364
365 struct s5p_hdmi_color_range {
366         u8      y_min;
367         u8      y_max;
368         u8      c_min;
369         u8      c_max;
370 };
371
372 struct s5p_hdmi_tg {
373         bool correction_en;
374         bool bt656_en;
375 };
376
377 struct s5p_hdmi_audio {
378         enum s5p_hdmi_audio_type        type;
379         u32                             freq;
380         u32                             bit;
381         u32                             channel;
382
383         u8                              on;
384 };
385
386 struct s5p_hdmi_video {
387         struct s5p_hdmi_color_range     color_r;
388         enum s5p_hdmi_pic_aspect        aspect;
389         enum s5p_hdmi_colorimetry       colorimetry;
390         enum s5p_hdmi_color_depth       depth;
391 };
392
393 struct s5p_hdmi_o_params {
394         struct s5p_hdmi_o_trans trans;
395         struct s5p_hdmi_o_reg   reg;
396 };
397
398 struct s5p_hdmi_ctrl_private_data {
399         u8                              vendor[8];
400         u8                              product[16];
401
402         enum s5p_tvout_o_mode           out;
403         enum s5p_hdmi_v_mode            mode;
404
405         struct s5p_hdmi_bluescreen      blue_screen;
406         struct s5p_hdmi_packet          packet;
407         struct s5p_hdmi_tg              tg;
408         struct s5p_hdmi_audio           audio;
409         struct s5p_hdmi_video           video;
410
411         bool                            hpd_status;
412         bool                            hdcp_en;
413
414         bool                            av_mute;
415
416         bool                            running;
417         char                            *pow_name;
418         struct s5p_tvout_clk_info               clk[HDMI_NO_OF_CLK];
419         struct reg_mem_info             reg_mem[HDMI_NO_OF_MEM_RES];
420         struct irq_info                 irq;
421 };
422
423 static struct s5p_hdmi_v_format s5p_hdmi_v_fmt[] = {
424         [v720x480p_60Hz] = {
425                 .frame = {
426                         .vic            = 2,
427                         .vic_16_9       = 3,
428                         .repetition     = 0,
429                         .polarity       = 1,
430                         .i_p            = 0,
431                         .h_active       = 720,
432                         .v_active       = 480,
433                         .h_total        = 858,
434                         .h_blank        = 138,
435                         .v_total        = 525,
436                         .v_blank        = 45,
437                         .pixel_clock    = ePHY_FREQ_27_027,
438                 },
439                 .h_sync = {
440                         .begin          = 0xe,
441                         .end            = 0x4c,
442                 },
443                 .v_sync_top = {
444                         .begin          = 0x9,
445                         .end            = 0xf,
446                 },
447                 .v_sync_bottom = {
448                         .begin          = 0,
449                         .end            = 0,
450                 },
451                 .v_sync_h_pos = {
452                         .begin          = 0,
453                         .end            = 0,
454                 },
455                 .v_blank_f = {
456                         .begin          = 0,
457                         .end            = 0,
458                 },
459                 .mhl_hsync = 0xf,
460                 .mhl_vsync = 0x1,
461         },
462
463         [v1280x720p_60Hz] = {
464                 .frame = {
465                         .vic            = 4,
466                         .vic_16_9       = 4,
467                         .repetition     = 0,
468                         .polarity       = 0,
469                         .i_p            = 0,
470                         .h_active       = 1280,
471                         .v_active       = 720,
472                         .h_total        = 1650,
473                         .h_blank        = 370,
474                         .v_total        = 750,
475                         .v_blank        = 30,
476                         .pixel_clock    = ePHY_FREQ_74_250,
477                 },
478                 .h_sync = {
479                         .begin          = 0x6c,
480                         .end            = 0x94,
481                 },
482                 .v_sync_top = {
483                         .begin          = 0x5,
484                         .end            = 0xa,
485                 },
486                 .v_sync_bottom = {
487                         .begin          = 0,
488                         .end            = 0,
489                 },
490                 .v_sync_h_pos = {
491                         .begin          = 0,
492                         .end            = 0,
493                 },
494                 .v_blank_f = {
495                         .begin          = 0,
496                         .end            = 0,
497                 },
498                 .mhl_hsync = 0xf,
499                 .mhl_vsync = 0x1,
500         },
501
502         [v1920x1080i_60Hz] = {
503                 .frame = {
504                         .vic            = 5,
505                         .vic_16_9       = 5,
506                         .repetition     = 0,
507                         .polarity       = 0,
508                         .i_p            = 1,
509                         .h_active       = 1920,
510                         .v_active       = 540,
511                         .h_total        = 2200,
512                         .h_blank        = 280,
513                         .v_total        = 1125,
514                         .v_blank        = 22,
515                         .pixel_clock    = ePHY_FREQ_74_250,
516                 },
517                 .h_sync = {
518                         .begin          = 0x56,
519                         .end            = 0x82,
520                 },
521                 .v_sync_top = {
522                         .begin          = 0x2,
523                         .end            = 0x7,
524                 },
525                 .v_sync_bottom = {
526                         .begin          = 0x234,
527                         .end            = 0x239,
528                 },
529                 .v_sync_h_pos = {
530                         .begin          = 0x4a4,
531                         .end            = 0x4a4,
532                 },
533                 .v_blank_f = {
534                         .begin          = 0x249,
535                         .end            = 0x465,
536                 },
537                 .mhl_hsync = 0xf,
538                 .mhl_vsync = 0x1,
539         },
540
541         [v1920x1080p_60Hz] = {
542                 .frame = {
543                         .vic            = 16,
544                         .vic_16_9       = 16,
545                         .repetition     = 0,
546                         .polarity       = 0,
547                         .i_p            = 0,
548                         .h_active       = 1920,
549                         .v_active       = 1080,
550                         .h_total        = 2200,
551                         .h_blank        = 280,
552                         .v_total        = 1125,
553                         .v_blank        = 45,
554                         .pixel_clock    = ePHY_FREQ_148_500,
555                 },
556                 .h_sync = {
557                         .begin          = 0x56,
558                         .end            = 0x82,
559                 },
560                 .v_sync_top = {
561                         .begin          = 0x4,
562                         .end            = 0x9,
563                 },
564                 .v_sync_bottom = {
565                         .begin          = 0,
566                         .end            = 0,
567                 },
568                 .v_sync_h_pos = {
569                         .begin          = 0,
570                         .end            = 0,
571                 },
572                 .v_blank_f = {
573                         .begin          = 0,
574                         .end            = 0,
575                 },
576                 .mhl_hsync = 0xf,
577                 .mhl_vsync = 0x1,
578         },
579
580         [v720x576p_50Hz] = {
581                 .frame = {
582                         .vic            = 17,
583                         .vic_16_9       = 18,
584                         .repetition     = 0,
585                         .polarity       = 1,
586                         .i_p            = 0,
587                         .h_active       = 720,
588                         .v_active       = 576,
589                         .h_total        = 864,
590                         .h_blank        = 144,
591                         .v_total        = 625,
592                         .v_blank        = 49,
593                         .pixel_clock    = ePHY_FREQ_27,
594                 },
595                 .h_sync = {
596                         .begin          = 0xa,
597                         .end            = 0x4a,
598                 },
599                 .v_sync_top = {
600                         .begin          = 0x5,
601                         .end            = 0xa,
602                 },
603                 .v_sync_bottom = {
604                         .begin          = 0,
605                         .end            = 0,
606                 },
607                 .v_sync_h_pos = {
608                         .begin          = 0,
609                         .end            = 0,
610                 },
611                 .v_blank_f = {
612                         .begin          = 0,
613                         .end            = 0,
614                 },
615                 .mhl_hsync = 0xf,
616                 .mhl_vsync = 0x1,
617         },
618
619         [v1280x720p_50Hz] = {
620                 .frame = {
621                         .vic            = 19,
622                         .vic_16_9       = 19,
623                         .repetition     = 0,
624                         .polarity       = 0,
625                         .i_p            = 0,
626                         .h_active       = 1280,
627                         .v_active       = 720,
628                         .h_total        = 1980,
629                         .h_blank        = 700,
630                         .v_total        = 750,
631                         .v_blank        = 30,
632                         .pixel_clock    = ePHY_FREQ_74_250,
633                 },
634                 .h_sync = {
635                         .begin          = 0x1b6,
636                         .end            = 0x1de,
637                 },
638                 .v_sync_top = {
639                         .begin          = 0x5,
640                         .end            = 0xa,
641                 },
642                 .v_sync_bottom = {
643                         .begin          = 0,
644                         .end            = 0,
645                 },
646                 .v_sync_h_pos = {
647                         .begin          = 0,
648                         .end            = 0,
649                 },
650                 .v_blank_f = {
651                         .begin          = 0,
652                         .end            = 0,
653                 },
654                 .mhl_hsync = 0xf,
655                 .mhl_vsync = 0x1,
656         },
657
658         [v1920x1080i_50Hz] = {
659                 .frame = {
660                         .vic            = 20,
661                         .vic_16_9       = 20,
662                         .repetition     = 0,
663                         .polarity       = 0,
664                         .i_p            = 1,
665                         .h_active       = 1920,
666                         .v_active       = 540,
667                         .h_total        = 2640,
668                         .h_blank        = 720,
669                         .v_total        = 1125,
670                         .v_blank        = 22,
671                         .pixel_clock    = ePHY_FREQ_74_250,
672                 },
673                 .h_sync = {
674                         .begin          = 0x20e,
675                         .end            = 0x23a,
676                 },
677                 .v_sync_top = {
678                         .begin          = 0x2,
679                         .end            = 0x7,
680                 },
681                 .v_sync_bottom = {
682                         .begin          = 0x234,
683                         .end            = 0x239,
684                 },
685                 .v_sync_h_pos = {
686                         .begin          = 0x738,
687                         .end            = 0x738,
688                 },
689                 .v_blank_f = {
690                         .begin          = 0x249,
691                         .end            = 0x465,
692                 },
693                 .mhl_hsync = 0xf,
694                 .mhl_vsync = 0x1,
695         },
696
697         [v1920x1080p_50Hz] = {
698                 .frame = {
699                         .vic            = 31,
700                         .vic_16_9       = 31,
701                         .repetition     = 0,
702                         .polarity       = 0,
703                         .i_p            = 0,
704                         .h_active       = 1920,
705                         .v_active       = 1080,
706                         .h_total        = 2640,
707                         .h_blank        = 720,
708                         .v_total        = 1125,
709                         .v_blank        = 45,
710                         .pixel_clock    = ePHY_FREQ_148_500,
711                 },
712                 .h_sync = {
713                         .begin          = 0x20e,
714                         .end            = 0x23a,
715                 },
716                 .v_sync_top = {
717                         .begin          = 0x4,
718                         .end            = 0x9,
719                 },
720                 .v_sync_bottom = {
721                         .begin          = 0,
722                         .end            = 0,
723                 },
724                 .v_sync_h_pos = {
725                         .begin          = 0,
726                         .end            = 0,
727                 },
728                 .v_blank_f = {
729                         .begin          = 0,
730                         .end            = 0,
731                 },
732                 .mhl_hsync = 0xf,
733                 .mhl_vsync = 0x1,
734         },
735
736         [v1920x1080p_30Hz] = {
737                 .frame = {
738                         .vic            = 34,
739                         .vic_16_9       = 34,
740                         .repetition     = 0,
741                         .polarity       = 0,
742                         .i_p            = 0,
743                         .h_active       = 1920,
744                         .v_active       = 1080,
745                         .h_total        = 2200,
746                         .h_blank        = 280,
747                         .v_total        = 1125,
748                         .v_blank        = 45,
749                         .pixel_clock    = ePHY_FREQ_74_250,
750                 },
751                 .h_sync = {
752                         .begin          = 0x56,
753                         .end            = 0x82,
754                 },
755                 .v_sync_top = {
756                         .begin          = 0x4,
757                         .end            = 0x9,
758                 },
759                 .v_sync_bottom = {
760                         .begin          = 0,
761                         .end            = 0,
762                 },
763                 .v_sync_h_pos = {
764                         .begin          = 0,
765                         .end            = 0,
766                 },
767                 .v_blank_f = {
768                         .begin          = 0,
769                         .end            = 0,
770                 },
771                 .mhl_hsync = 0xf,
772                 .mhl_vsync = 0x1,
773         },
774
775         [v720x480p_59Hz] = {
776                 .frame = {
777                         .vic            = 2,
778                         .vic_16_9       = 3,
779                         .repetition     = 0,
780                         .polarity       = 1,
781                         .i_p            = 0,
782                         .h_active       = 720,
783                         .v_active       = 480,
784                         .h_total        = 858,
785                         .h_blank        = 138,
786                         .v_total        = 525,
787                         .v_blank        = 45,
788                         .pixel_clock    = ePHY_FREQ_27,
789                 },
790                 .h_sync = {
791                         .begin          = 0xe,
792                         .end            = 0x4c,
793                 },
794                 .v_sync_top = {
795                         .begin          = 0x9,
796                         .end            = 0xf,
797                 },
798                 .v_sync_bottom = {
799                         .begin          = 0,
800                         .end            = 0,
801                 },
802                 .v_sync_h_pos = {
803                         .begin          = 0,
804                         .end            = 0,
805                 },
806                 .v_blank_f = {
807                         .begin          = 0,
808                         .end            = 0,
809                 },
810                 .mhl_hsync = 0xf,
811                 .mhl_vsync = 0x1,
812         },
813
814         [v1280x720p_59Hz] = {
815                 .frame = {
816                         .vic            = 4,
817                         .vic_16_9       = 4,
818                         .repetition     = 0,
819                         .polarity       = 0,
820                         .i_p            = 0,
821                         .h_active       = 1280,
822                         .v_active       = 720,
823                         .h_total        = 1650,
824                         .h_blank        = 370,
825                         .v_total        = 750,
826                         .v_blank        = 30,
827                         .pixel_clock    = ePHY_FREQ_74_176,
828                 },
829                 .h_sync = {
830                         .begin          = 0x6c,
831                         .end            = 0x94,
832                 },
833                 .v_sync_top = {
834                         .begin          = 0x5,
835                         .end            = 0xa,
836                 },
837                 .v_sync_bottom = {
838                         .begin          = 0,
839                         .end            = 0,
840                 },
841                 .v_sync_h_pos = {
842                         .begin          = 0,
843                         .end            = 0,
844                 },
845                 .v_blank_f = {
846                         .begin          = 0,
847                         .end            = 0,
848                 },
849                 .mhl_hsync = 0xf,
850                 .mhl_vsync = 0x1,
851         },
852
853         [v1920x1080i_59Hz] = {
854                 .frame = {
855                         .vic            = 5,
856                         .vic_16_9       = 5,
857                         .repetition     = 0,
858                         .polarity       = 0,
859                         .i_p            = 1,
860                         .h_active       = 1920,
861                         .v_active       = 540,
862                         .h_total        = 2200,
863                         .h_blank        = 280,
864                         .v_total        = 1125,
865                         .v_blank        = 22,
866                         .pixel_clock    = ePHY_FREQ_74_176,
867                 },
868                 .h_sync = {
869                         .begin          = 0x56,
870                         .end            = 0x82,
871                 },
872                 .v_sync_top = {
873                         .begin          = 0x2,
874                         .end            = 0x7,
875                 },
876                 .v_sync_bottom = {
877                         .begin          = 0x234,
878                         .end            = 0x239,
879                 },
880                 .v_sync_h_pos = {
881                         .begin          = 0x4a4,
882                         .end            = 0x4a4,
883                 },
884                 .v_blank_f = {
885                         .begin          = 0x249,
886                         .end            = 0x465,
887                 },
888                 .mhl_hsync = 0xf,
889                 .mhl_vsync = 0x1,
890         },
891
892         [v1920x1080p_59Hz] = {
893                 .frame = {
894                         .vic            = 16,
895                         .vic_16_9       = 16,
896                         .repetition     = 0,
897                         .polarity       = 0,
898                         .i_p            = 0,
899                         .h_active       = 1920,
900                         .v_active       = 1080,
901                         .h_total        = 2200,
902                         .h_blank        = 280,
903                         .v_total        = 1125,
904                         .v_blank        = 45,
905                         .pixel_clock    = ePHY_FREQ_148_352,
906                 },
907                 .h_sync = {
908                         .begin          = 0x56,
909                         .end            = 0x82,
910                 },
911                 .v_sync_top = {
912                         .begin          = 0x4,
913                         .end            = 0x9,
914                 },
915                 .v_sync_bottom = {
916                         .begin          = 0,
917                         .end            = 0,
918                 },
919                 .v_sync_h_pos = {
920                         .begin          = 0,
921                         .end            = 0,
922                 },
923                 .v_blank_f = {
924                         .begin          = 0,
925                         .end            = 0,
926                 },
927                 .mhl_hsync = 0xf,
928                 .mhl_vsync = 0x1,
929         },
930 };
931
932 static struct s5p_hdmi_o_params s5p_hdmi_output[] = {
933         {
934                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
935                 {0x00, 0x00, 0x00, 0x00, 0x00},
936         }, {
937                 {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04},
938                 {0x40, 0x00, 0x02, 0x00, 0x00},
939         }, {
940                 {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04},
941                 {0x00, 0x00, 0x02, 0x20, 0x00},
942         }, {
943                 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
944                 {0x00, 0x22, 0x01, 0x20, 0x01},
945         },
946 };
947
948 static struct s5p_hdmi_ctrl_private_data s5p_hdmi_ctrl_private = {
949         .vendor         = "SAMSUNG",
950         .product        = "S5PC210",
951
952         .blue_screen = {
953                 .enable = false,
954                 .cb_b   = 0,
955                 .y_g    = 0,
956                 .cr_r   = 0,
957         },
958
959         .video = {
960                 .color_r = {
961                         .y_min = 1,
962                         .y_max = 254,
963                         .c_min = 1,
964                         .c_max = 254,
965                 },
966                 .depth  = HDMI_CD_24,
967         },
968
969         .packet = {
970                 .vsi_info = {0x81, 0x1, 27},
971                 .avi_info = {0x82, 0x2, 13},
972                 .spd_info = {0x83, 0x1, 27},
973                 .aui_info = {0x84, 0x1, 5},
974                 .mpg_info = {0x85, 0x1, 5},
975         },
976
977         .tg = {
978                 .correction_en  = false,
979                 .bt656_en       = false,
980         },
981
982         .hdcp_en = false,
983
984         .audio = {
985                 .type   = HDMI_60958_AUDIO,
986                 .bit    = 16,
987                 .freq   = 44100,
988         },
989
990         .av_mute        = false,
991         .running        = false,
992
993         .pow_name = "hdmi_pd",
994
995         .clk[HDMI_PCLK] = {
996                 .name = "hdmi",
997                 .ptr = NULL
998         },
999
1000         .clk[HDMI_MUX] = {
1001                 .name = "sclk_hdmi",
1002                 .ptr = NULL
1003         },
1004
1005         .reg_mem[HDMI] = {
1006                 .name = "s5p-hdmi",
1007                 .res = NULL,
1008                 .base = NULL
1009         },
1010
1011         .reg_mem[HDMI_PHY] = {
1012                 .name = "s5p-i2c-hdmi-phy",
1013                 .res = NULL,
1014                 .base = NULL
1015         },
1016
1017         .irq = {
1018                 .name = "s5p-hdmi",
1019                 .handler = s5p_hdmi_irq,
1020                 .no = -1
1021         }
1022
1023 };
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 /****************************************
1034  * Definitions for tvif ctrl class
1035  ***************************************/
1036 struct s5p_tvif_ctrl_private_data {
1037         enum s5p_tvout_disp_mode        curr_std;
1038         enum s5p_tvout_o_mode           curr_if;
1039
1040         bool                            running;
1041 };
1042
1043 static struct s5p_tvif_ctrl_private_data s5p_tvif_ctrl_private = {
1044         .curr_std = TVOUT_INIT_DISP_VALUE,
1045         .curr_if = TVOUT_INIT_O_VALUE,
1046
1047         .running = false
1048 };
1049
1050
1051
1052
1053
1054
1055
1056 /****************************************
1057  * Functions for sdo ctrl class
1058  ***************************************/
1059
1060 static void s5p_sdo_ctrl_init_private(void)
1061 {
1062 }
1063
1064 static int s5p_sdo_ctrl_set_reg(enum s5p_tvout_disp_mode disp_mode)
1065 {
1066         struct s5p_sdo_ctrl_private_data *private = &s5p_sdo_ctrl_private;
1067
1068         s5p_sdo_sw_reset(1);
1069
1070         if (s5p_sdo_set_display_mode(disp_mode, SDO_O_ORDER_COMPOSITE_Y_C_CVBS))
1071                 return -1;
1072
1073         if (s5p_sdo_set_video_scale_cfg(
1074                 private->video_scale_cfg.composite_level,
1075                 private->video_scale_cfg.composite_ratio))
1076                 return -1;
1077
1078         if (s5p_sdo_set_vbi(
1079                 private->vbi.wss_cvbs, private->vbi.caption_cvbs))
1080                 return -1;
1081
1082         s5p_sdo_set_offset_gain(
1083                 private->offset_gain.offset, private->offset_gain.gain);
1084
1085         s5p_sdo_set_delay(
1086                 private->delay.delay_y,
1087                 private->delay.offset_video_start,
1088                 private->delay.offset_video_end);
1089
1090         s5p_sdo_set_schlock(private->color_sub_carrier_phase_adj);
1091
1092         s5p_sdo_set_brightness_hue_saturation(private->bri_hue_sat);
1093
1094         s5p_sdo_set_cvbs_color_compensation(private->cvbs_compen);
1095
1096         s5p_sdo_set_component_porch(
1097                 private->compo_porch.back_525,
1098                 private->compo_porch.front_525,
1099                 private->compo_porch.back_625,
1100                 private->compo_porch.front_625);
1101
1102         s5p_sdo_set_ch_xtalk_cancel_coef(
1103                 private->xtalk_cc.coeff2, private->xtalk_cc.coeff1);
1104
1105         s5p_sdo_set_closed_caption(
1106                 private->closed_cap.display_cc,
1107                 private->closed_cap.nondisplay_cc);
1108
1109         if (s5p_sdo_set_wss525_data(private->wss_525))
1110                 return -1;
1111
1112         if (s5p_sdo_set_wss625_data(private->wss_625))
1113                 return -1;
1114
1115         if (s5p_sdo_set_cgmsa525_data(private->cgms_525))
1116                 return -1;
1117
1118         if (s5p_sdo_set_cgmsa625_data(private->cgms_625))
1119                 return -1;
1120
1121         s5p_sdo_set_interrupt_enable(0);
1122
1123         s5p_sdo_clear_interrupt_pending();
1124
1125         s5p_sdo_clock_on(1);
1126         s5p_sdo_dac_on(1);
1127
1128         return 0;
1129 }
1130
1131 static void s5p_sdo_ctrl_internal_stop(void)
1132 {
1133         s5p_sdo_clock_on(0);
1134         s5p_sdo_dac_on(0);
1135 }
1136
1137 static void s5p_sdo_ctrl_clock(bool on)
1138 {
1139         if (on) {
1140                 clk_enable(s5p_sdo_ctrl_private.clk[SDO_MUX].ptr);
1141
1142 #ifdef CONFIG_CPU_S5PV210
1143                 s5pv210_pd_enable(s5p_sdo_ctrl_private.pow_name);
1144 #endif
1145
1146 #ifdef CONFIG_CPU_S5PV310
1147                 s5p_tvout_pm_runtime_get();
1148 #endif
1149
1150                 clk_enable(s5p_sdo_ctrl_private.clk[SDO_PCLK].ptr);
1151         } else {
1152                 clk_disable(s5p_sdo_ctrl_private.clk[SDO_PCLK].ptr);
1153
1154 #ifdef CONFIG_CPU_S5PV210
1155                 s5pv210_pd_disable(s5p_sdo_ctrl_private.pow_name);
1156 #endif
1157
1158 #ifdef CONFIG_CPU_S5PV310
1159                 s5p_tvout_pm_runtime_put();
1160 #endif
1161
1162                 clk_disable(s5p_sdo_ctrl_private.clk[SDO_MUX].ptr);
1163         }
1164
1165         mdelay(50);
1166 }
1167
1168 void s5p_sdo_ctrl_stop(void)
1169 {
1170         if (s5p_sdo_ctrl_private.running) {
1171                 s5p_sdo_ctrl_internal_stop();
1172                 s5p_sdo_ctrl_clock(0);
1173
1174                 s5p_sdo_ctrl_private.running = false;
1175         }
1176 }
1177
1178 int s5p_sdo_ctrl_start(enum s5p_tvout_disp_mode disp_mode)
1179 {
1180         struct s5p_sdo_ctrl_private_data *sdo_private = &s5p_sdo_ctrl_private;
1181
1182         switch (disp_mode) {
1183         case TVOUT_NTSC_M:
1184         case TVOUT_NTSC_443:
1185                 sdo_private->video_scale_cfg.composite_level =
1186                         SDO_LEVEL_75IRE;
1187                 sdo_private->video_scale_cfg.composite_ratio =
1188                         SDO_VTOS_RATIO_10_4;
1189                 break;
1190
1191         case TVOUT_PAL_BDGHI:
1192         case TVOUT_PAL_M:
1193         case TVOUT_PAL_N:
1194         case TVOUT_PAL_NC:
1195         case TVOUT_PAL_60:
1196                 sdo_private->video_scale_cfg.composite_level =
1197                         SDO_LEVEL_0IRE;
1198                 sdo_private->video_scale_cfg.composite_ratio =
1199                         SDO_VTOS_RATIO_7_3;
1200                 break;
1201
1202         default:
1203                 tvout_err("invalid disp_mode(%d) for SDO\n",
1204                         disp_mode);
1205                 goto err_on_s5p_sdo_start;
1206         }
1207
1208         if (sdo_private->running)
1209                 s5p_sdo_ctrl_internal_stop();
1210         else {
1211                 s5p_sdo_ctrl_clock(1);
1212
1213                 sdo_private->running = true;
1214         }
1215
1216         if (s5p_sdo_ctrl_set_reg(disp_mode))
1217                 goto err_on_s5p_sdo_start;
1218
1219         return 0;
1220
1221 err_on_s5p_sdo_start:
1222         return -1;
1223 }
1224
1225 int s5p_sdo_ctrl_constructor(struct platform_device *pdev)
1226 {
1227         int ret;
1228         int i, j;
1229
1230         ret = s5p_tvout_map_resource_mem(
1231                 pdev,
1232                 s5p_sdo_ctrl_private.reg_mem.name,
1233                 &(s5p_sdo_ctrl_private.reg_mem.base),
1234                 &(s5p_sdo_ctrl_private.reg_mem.res));
1235
1236         if (ret)
1237                 goto err_on_res;
1238
1239         for (i = SDO_PCLK; i < SDO_NO_OF_CLK; i++) {
1240                 s5p_sdo_ctrl_private.clk[i].ptr =
1241                         clk_get(&pdev->dev, s5p_sdo_ctrl_private.clk[i].name);
1242
1243                 if (IS_ERR(s5p_sdo_ctrl_private.clk[i].ptr)) {
1244                         tvout_err("Failed to find clock %s\n",
1245                                         s5p_sdo_ctrl_private.clk[i].name);
1246                         ret = -ENOENT;
1247                         goto err_on_clk;
1248                 }
1249         }
1250
1251         s5p_sdo_ctrl_init_private();
1252         s5p_sdo_init(s5p_sdo_ctrl_private.reg_mem.base);
1253
1254         return 0;
1255
1256 err_on_clk:
1257         for (j = 0; j < i; j++)
1258                 clk_put(s5p_sdo_ctrl_private.clk[j].ptr);
1259
1260         s5p_tvout_unmap_resource_mem(
1261                 s5p_sdo_ctrl_private.reg_mem.base,
1262                 s5p_sdo_ctrl_private.reg_mem.res);
1263
1264 err_on_res:
1265         return ret;
1266 }
1267
1268 void s5p_sdo_ctrl_destructor(void)
1269 {
1270         int i;
1271
1272         s5p_tvout_unmap_resource_mem(
1273                 s5p_sdo_ctrl_private.reg_mem.base,
1274                 s5p_sdo_ctrl_private.reg_mem.res);
1275
1276         for (i = SDO_PCLK; i < SDO_NO_OF_CLK; i++)
1277                 if (s5p_sdo_ctrl_private.clk[i].ptr) {
1278                         if (s5p_sdo_ctrl_private.running)
1279                                 clk_disable(s5p_sdo_ctrl_private.clk[i].ptr);
1280                         clk_put(s5p_sdo_ctrl_private.clk[i].ptr);
1281         }
1282 }
1283
1284
1285
1286
1287
1288
1289 /****************************************
1290  * Functions for hdmi ctrl class
1291  ***************************************/
1292
1293 static enum s5p_hdmi_v_mode s5p_hdmi_check_v_fmt(enum s5p_tvout_disp_mode disp)
1294 {
1295         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1296         struct s5p_hdmi_video                   *video = &ctrl->video;
1297         enum s5p_hdmi_v_mode                    mode;
1298
1299         video->aspect           = HDMI_PIC_RATIO_16_9;
1300         video->colorimetry      = HDMI_CLRIMETRY_601;
1301
1302         switch (disp) {
1303         case TVOUT_480P_60_16_9:
1304                 mode = v720x480p_60Hz;
1305                 break;
1306
1307         case TVOUT_480P_60_4_3:
1308                 mode = v720x480p_60Hz;
1309                 video->aspect = HDMI_PIC_RATIO_4_3;
1310                 break;
1311
1312         case TVOUT_480P_59:
1313                 mode = v720x480p_59Hz;
1314                 break;
1315
1316         case TVOUT_576P_50_16_9:
1317                 mode = v720x576p_50Hz;
1318                 break;
1319
1320         case TVOUT_576P_50_4_3:
1321                 mode = v720x576p_50Hz;
1322                 video->aspect = HDMI_PIC_RATIO_4_3;
1323                 break;
1324
1325         case TVOUT_720P_60:
1326                 mode = v1280x720p_60Hz;
1327                 video->colorimetry = HDMI_CLRIMETRY_709;
1328                 break;
1329
1330         case TVOUT_720P_59:
1331                 mode = v1280x720p_59Hz;
1332                 video->colorimetry = HDMI_CLRIMETRY_709;
1333                 break;
1334
1335         case TVOUT_720P_50:
1336                 mode = v1280x720p_50Hz;
1337                 video->colorimetry = HDMI_CLRIMETRY_709;
1338                 break;
1339
1340         case TVOUT_1080P_30:
1341                 mode = v1920x1080p_30Hz;
1342                 video->colorimetry = HDMI_CLRIMETRY_709;
1343                 break;
1344
1345         case TVOUT_1080P_60:
1346                 mode = v1920x1080p_60Hz;
1347                 video->colorimetry = HDMI_CLRIMETRY_709;
1348                 break;
1349
1350         case TVOUT_1080P_59:
1351                 mode = v1920x1080p_59Hz;
1352                 video->colorimetry = HDMI_CLRIMETRY_709;
1353                 break;
1354
1355         case TVOUT_1080P_50:
1356                 mode = v1920x1080p_50Hz;
1357                 video->colorimetry = HDMI_CLRIMETRY_709;
1358                 break;
1359
1360         case TVOUT_1080I_60:
1361                 mode = v1920x1080i_60Hz;
1362                 video->colorimetry = HDMI_CLRIMETRY_709;
1363                 break;
1364
1365         case TVOUT_1080I_59:
1366                 mode = v1920x1080i_59Hz;
1367                 video->colorimetry = HDMI_CLRIMETRY_709;
1368                 break;
1369
1370         case TVOUT_1080I_50:
1371                 mode = v1920x1080i_50Hz;
1372                 video->colorimetry = HDMI_CLRIMETRY_709;
1373                 break;
1374
1375         default:
1376                 mode = v720x480p_60Hz;
1377                 tvout_err("Not supported mode : %d\n", mode);
1378         }
1379
1380         return mode;
1381 }
1382
1383 static void s5p_hdmi_set_acr(struct s5p_hdmi_audio *audio, u8 *acr)
1384 {
1385         u32 n = (audio->freq == 32000) ? 4096 :
1386                 (audio->freq == 44100) ? 6272 :
1387                 (audio->freq == 88200) ? 12544 :
1388                 (audio->freq == 176400) ? 25088 :
1389                 (audio->freq == 48000) ? 6144 :
1390                 (audio->freq == 96000) ? 12288 :
1391                 (audio->freq == 192000) ? 24576 : 0;
1392
1393         u32 cts = (audio->freq == 32000) ? 27000 :
1394                 (audio->freq == 44100) ? 30000 :
1395                 (audio->freq == 88200) ? 30000 :
1396                 (audio->freq == 176400) ? 30000 :
1397                 (audio->freq == 48000) ? 27000 :
1398                 (audio->freq == 96000) ? 27000 :
1399                 (audio->freq == 192000) ? 27000 : 0;
1400
1401         acr[1] = cts >> 16;
1402         acr[2] = cts >> 8 & 0xff;
1403         acr[3] = cts & 0xff;
1404
1405         acr[4] = n >> 16;
1406         acr[5] = n >> 8 & 0xff;
1407         acr[6] = n & 0xff;
1408
1409         tvout_dbg("n value = %d\n", n);
1410         tvout_dbg("cts   = %d\n", cts);
1411 }
1412
1413 static void s5p_hdmi_set_asp(u8 *header)
1414 {
1415         header[1] = 0;
1416         header[2] = 0;
1417 }
1418
1419 static void s5p_hdmi_set_acp(struct s5p_hdmi_audio *audio, u8 *header)
1420 {
1421         header[1] = audio->type;
1422 }
1423
1424 static void s5p_hdmi_set_isrc(u8 *header)
1425 {
1426 }
1427
1428 static void s5p_hdmi_set_gmp(u8 *gmp)
1429 {
1430 }
1431
1432 static void s5p_hdmi_set_avi(
1433         enum s5p_hdmi_v_mode mode, enum s5p_tvout_o_mode out,
1434         struct s5p_hdmi_video *video, u8 *avi)
1435 {
1436         struct s5p_hdmi_o_params                param = s5p_hdmi_output[out];
1437         struct s5p_hdmi_v_frame                 frame;
1438
1439         frame = s5p_hdmi_v_fmt[mode].frame;
1440
1441         avi[0] = param.reg.pxl_fmt;
1442         avi[0] |= (0x1 << 4);
1443
1444         avi[1] = video->colorimetry;
1445         avi[1] |= video->aspect << 4;
1446         avi[1] |= AVI_SAME_WITH_PICTURE_AR;
1447
1448         avi[3] = (video->aspect == HDMI_PIC_RATIO_16_9) ?
1449                                 frame.vic_16_9 : frame.vic;
1450
1451         avi[4] = frame.repetition;
1452 }
1453
1454 static void s5p_hdmi_set_aui(struct s5p_hdmi_audio *audio, u8 *aui)
1455 {
1456         aui[0] = (0 << 4) | audio->channel;
1457         aui[1] = ((audio->type == HDMI_60958_AUDIO) ? 0 : audio->freq << 2) | 0;
1458         aui[2] = 0;
1459 }
1460
1461 static void s5p_hdmi_set_spd(u8 *spd)
1462 {
1463         struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1464
1465         memcpy(spd, ctrl->vendor, 8);
1466         memcpy(&spd[8], ctrl->product, 16);
1467
1468         spd[24] = 0x1; /* Digital STB */
1469 }
1470
1471 static void s5p_hdmi_set_mpg(u8 *mpg)
1472 {
1473 }
1474
1475 static int s5p_hdmi_ctrl_audio_enable(bool en)
1476 {
1477         if (!s5p_hdmi_output[s5p_hdmi_ctrl_private.out].reg.dvi)
1478                 s5p_hdmi_reg_audio_enable(en);
1479
1480         return 0;
1481 }
1482
1483 #if 0 /* This function will be used in the future */
1484 static void s5p_hdmi_ctrl_bluescreen_clr(u8 cb_b, u8 y_g, u8 cr_r)
1485 {
1486         struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1487
1488         ctrl->blue_screen.cb_b  = cb_b;
1489         ctrl->blue_screen.y_g   = y_g;
1490         ctrl->blue_screen.cr_r  = cr_r;
1491
1492         s5p_hdmi_reg_bluescreen_clr(cb_b, y_g, cr_r);
1493 }
1494 #endif
1495
1496 static void s5p_hdmi_ctrl_set_bluescreen(bool en)
1497 {
1498         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1499
1500         ctrl->blue_screen.enable = en ? true : false;
1501
1502         s5p_hdmi_reg_bluescreen(en);
1503 }
1504
1505 static void s5p_hdmi_ctrl_set_audio(bool en)
1506 {
1507         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1508
1509         s5p_hdmi_ctrl_private.audio.on = en ? 1 : 0;
1510
1511         if (ctrl->running)
1512                 s5p_hdmi_ctrl_audio_enable(en);
1513 }
1514
1515 static void s5p_hdmi_ctrl_set_av_mute(bool en)
1516 {
1517         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1518
1519         ctrl->av_mute = en ? 1 : 0;
1520
1521         if (ctrl->running) {
1522                 if (en) {
1523                         s5p_hdmi_ctrl_audio_enable(false);
1524                         s5p_hdmi_ctrl_set_bluescreen(true);
1525                 } else {
1526                         s5p_hdmi_ctrl_audio_enable(true);
1527                         s5p_hdmi_ctrl_set_bluescreen(false);
1528                 }
1529         }
1530
1531 }
1532
1533 u8 s5p_hdmi_ctrl_get_mute(void)
1534 {
1535         return s5p_hdmi_ctrl_private.av_mute ? 1 : 0;
1536 }
1537
1538 #if 0 /* This function will be used in the future */
1539 static void s5p_hdmi_ctrl_mute(bool en)
1540 {
1541         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1542
1543         if (en) {
1544                 s5p_hdmi_reg_bluescreen(true);
1545                 s5p_hdmi_ctrl_audio_enable(false);
1546         } else {
1547                 s5p_hdmi_reg_bluescreen(false);
1548                 if (ctrl->audio.on)
1549                         s5p_hdmi_ctrl_audio_enable(true);
1550         }
1551 }
1552 #endif
1553
1554 void s5p_hdmi_ctrl_set_hdcp(bool en)
1555 {
1556         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1557
1558         ctrl->hdcp_en = en ? 1 : 0;
1559 }
1560
1561 static void s5p_hdmi_ctrl_init_private(void)
1562 {
1563 }
1564
1565 static bool s5p_hdmi_ctrl_set_reg(
1566                 enum s5p_hdmi_v_mode mode, enum s5p_tvout_o_mode out)
1567 {
1568         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1569         struct s5p_hdmi_packet                  *packet = &ctrl->packet;
1570
1571         struct s5p_hdmi_bluescreen              *bl = &ctrl->blue_screen;
1572         struct s5p_hdmi_color_range             *cr = &ctrl->video.color_r;
1573         struct s5p_hdmi_tg                      *tg = &ctrl->tg;
1574
1575         s5p_hdmi_reg_bluescreen_clr(bl->cb_b, bl->y_g, bl->cr_r);
1576         s5p_hdmi_reg_bluescreen(bl->enable);
1577
1578         s5p_hdmi_reg_clr_range(cr->y_min, cr->y_max, cr->c_min, cr->c_max);
1579
1580         s5p_hdmi_reg_acr(packet->acr);
1581         s5p_hdmi_reg_asp(packet->h_asp);
1582         s5p_hdmi_reg_gcp(s5p_hdmi_v_fmt[mode].frame.i_p, packet->gcp);
1583
1584         s5p_hdmi_reg_acp(packet->h_acp, packet->acp);
1585         s5p_hdmi_reg_isrc(packet->isrc1, packet->isrc2);
1586         s5p_hdmi_reg_gmp(packet->gmp);
1587
1588         s5p_hdmi_reg_infoframe(&packet->avi_info, packet->avi);
1589         s5p_hdmi_reg_infoframe(&packet->aui_info, packet->aui);
1590         s5p_hdmi_reg_infoframe(&packet->spd_info, packet->spd);
1591         s5p_hdmi_reg_infoframe(&packet->mpg_info, packet->mpg);
1592
1593         s5p_hdmi_reg_packet_trans(&s5p_hdmi_output[out].trans);
1594         s5p_hdmi_reg_output(&s5p_hdmi_output[out].reg);
1595
1596         s5p_hdmi_reg_tg(&s5p_hdmi_v_fmt[mode].frame);
1597         s5p_hdmi_reg_v_timing(&s5p_hdmi_v_fmt[mode]);
1598         s5p_hdmi_reg_tg_cmd(tg->correction_en, tg->bt656_en, true);
1599
1600         switch (ctrl->audio.type) {
1601         case HDMI_GENERIC_AUDIO:
1602                 break;
1603
1604         case HDMI_60958_AUDIO:
1605                 s5p_hdmi_audio_init(PCM, 44100, 16, 0);
1606                 break;
1607
1608         case HDMI_DVD_AUDIO:
1609         case HDMI_SUPER_AUDIO:
1610                 break;
1611
1612         default:
1613                 tvout_err("Invalid audio type %d\n", ctrl->audio.type);
1614                 return -1;
1615         }
1616
1617         s5p_hdmi_reg_audio_enable(true);
1618
1619         return 0;
1620 }
1621
1622 static void s5p_hdmi_ctrl_internal_stop(void)
1623 {
1624         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1625         struct s5p_hdmi_tg                      *tg = &ctrl->tg;
1626
1627 #ifdef CONFIG_HDMI_HPD
1628         s5p_hpd_set_eint();
1629 #endif
1630         if (ctrl->hdcp_en)
1631                 s5p_hdcp_stop();
1632
1633         mdelay(10);
1634
1635         s5p_hdmi_reg_enable(false);
1636
1637         s5p_hdmi_reg_tg_cmd(tg->correction_en, tg->bt656_en, false);
1638 }
1639
1640 int s5p_hdmi_ctrl_phy_power(bool on)
1641 {
1642         if (on) {
1643                 /* on */
1644                 clk_enable(s5ptv_status.i2c_phy_clk);
1645
1646                 s5p_hdmi_phy_power(true);
1647
1648
1649         } else {
1650                 /*
1651                  * for preventing hdmi hang up when restart
1652                  * switch to internal clk - SCLK_DAC, SCLK_PIXEL
1653                  */
1654                 s5p_mixer_ctrl_mux_clk(s5ptv_status.sclk_dac);
1655                 clk_set_parent(s5ptv_status.sclk_hdmi,
1656                                         s5ptv_status.sclk_pixel);
1657
1658                 s5p_hdmi_phy_power(false);
1659
1660                 clk_disable(s5ptv_status.i2c_phy_clk);
1661         }
1662
1663         return 0;
1664 }
1665
1666 static void s5p_hdmi_ctrl_clock(bool on)
1667 {
1668         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1669         struct s5p_tvout_clk_info               *clk = ctrl->clk;
1670
1671         if (on) {
1672                 clk_enable(clk[HDMI_MUX].ptr);
1673
1674 #ifdef CONFIG_CPU_S5PV210
1675                 s5pv210_pd_enable(ctrl->pow_name);
1676 #endif
1677
1678 #ifdef CONFIG_CPU_S5PV310
1679                 s5p_tvout_pm_runtime_get();
1680 #endif
1681
1682                 clk_enable(clk[HDMI_PCLK].ptr);
1683         } else {
1684                 clk_disable(clk[HDMI_PCLK].ptr);
1685
1686 #ifdef CONFIG_CPU_S5PV210
1687                 s5pv210_pd_disable(ctrl->pow_name);
1688 #endif
1689
1690 #ifdef CONFIG_CPU_S5PV310
1691                 s5p_tvout_pm_runtime_put();
1692 #endif
1693
1694                 clk_disable(clk[HDMI_MUX].ptr);
1695         }
1696
1697         mdelay(50);
1698 }
1699
1700 void s5p_hdmi_ctrl_stop(void)
1701 {
1702         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1703
1704         if (ctrl->running) {
1705                 s5p_hdmi_ctrl_internal_stop();
1706                 s5p_hdmi_ctrl_clock(0);
1707
1708                 ctrl->running = false;
1709         }
1710 }
1711
1712 int s5p_hdmi_ctrl_start(
1713         enum s5p_tvout_disp_mode disp, enum s5p_tvout_o_mode out)
1714 {
1715         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1716         struct s5p_hdmi_packet                  *packet = &ctrl->packet;
1717         struct s5p_hdmi_v_frame                 frame;
1718
1719         enum s5p_hdmi_v_mode                    mode;
1720
1721         ctrl->out = out;
1722         mode = s5p_hdmi_check_v_fmt(disp);
1723         ctrl->mode = mode;
1724
1725         if (ctrl->running)
1726                 s5p_hdmi_ctrl_internal_stop();
1727         else {
1728                 s5p_hdmi_ctrl_clock(1);
1729                 ctrl->running = true;
1730         }
1731
1732 #ifdef CONFIG_HDMI_HPD
1733         s5p_hpd_set_hdmiint();
1734 #endif
1735
1736         frame = s5p_hdmi_v_fmt[mode].frame;
1737
1738         if (s5p_hdmi_phy_config(frame.pixel_clock, ctrl->video.depth) < 0) {
1739                 tvout_err("hdmi phy configuration failed.\n");
1740                 goto err_on_s5p_hdmi_start;
1741         }
1742
1743
1744         s5p_hdmi_set_acr(&ctrl->audio, packet->acr);
1745         s5p_hdmi_set_asp(packet->h_asp);
1746         s5p_hdmi_set_gcp(ctrl->video.depth, packet->gcp);
1747
1748         s5p_hdmi_set_acp(&ctrl->audio, packet->h_acp);
1749         s5p_hdmi_set_isrc(packet->h_isrc);
1750         s5p_hdmi_set_gmp(packet->gmp);
1751
1752         s5p_hdmi_set_avi(mode, out, &ctrl->video, packet->avi);
1753         s5p_hdmi_set_spd(packet->spd);
1754         s5p_hdmi_set_aui(&ctrl->audio, packet->aui);
1755         s5p_hdmi_set_mpg(packet->mpg);
1756
1757         s5p_hdmi_ctrl_set_reg(mode, out);
1758
1759         s5p_hdmi_reg_enable(true);
1760
1761         if (ctrl->hdcp_en)
1762                 s5p_hdcp_start();
1763
1764         return 0;
1765
1766 err_on_s5p_hdmi_start:
1767         return -1;
1768 }
1769
1770 int s5p_hdmi_ctrl_constructor(struct platform_device *pdev)
1771 {
1772         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1773         struct reg_mem_info             *reg_mem = ctrl->reg_mem;
1774         struct s5p_tvout_clk_info               *clk = ctrl->clk;
1775         struct irq_info                 *irq = &ctrl->irq;
1776         int ret, i, k, j;
1777
1778         for (i = 0; i < HDMI_NO_OF_MEM_RES; i++) {
1779                 ret = s5p_tvout_map_resource_mem(pdev, reg_mem[i].name,
1780                         &(reg_mem[i].base), &(reg_mem[i].res));
1781
1782                 if (ret)
1783                         goto err_on_res;
1784         }
1785
1786         for (k = HDMI_PCLK; k < HDMI_NO_OF_CLK; k++) {
1787                 clk[k].ptr = clk_get(&pdev->dev, clk[k].name);
1788
1789                 if (IS_ERR(clk[k].ptr)) {
1790                         printk(KERN_ERR "%s clk is not found\n", clk[k].name);
1791                         ret = -ENOENT;
1792                         goto err_on_clk;
1793                 }
1794         }
1795
1796         irq->no = platform_get_irq_byname(pdev, irq->name);
1797
1798         if (irq->no < 0) {
1799                 printk(KERN_ERR "can not get platform irq by name : %s\n",
1800                                         irq->name);
1801                 ret = irq->no;
1802                 goto err_on_irq;
1803         }
1804
1805         ret = request_irq(irq->no, irq->handler, IRQF_DISABLED,
1806                         irq->name, NULL);
1807         if (ret) {
1808                 printk(KERN_ERR "can not request irq : %s\n", irq->name);
1809                 goto err_on_irq;
1810         }
1811
1812         s5p_hdmi_ctrl_init_private();
1813         s5p_hdmi_init(reg_mem[HDMI].base, reg_mem[HDMI_PHY].base);
1814
1815         /* set initial state of HDMI PHY power to off */
1816         s5p_hdmi_ctrl_phy_power(1);
1817         s5p_hdmi_ctrl_phy_power(0);
1818
1819         s5p_hdcp_init();
1820
1821         return 0;
1822
1823 err_on_irq:
1824 err_on_clk:
1825         for (j = 0; j < k; j++)
1826                 clk_put(clk[j].ptr);
1827
1828 err_on_res:
1829         for (j = 0; j < i; j++)
1830                 s5p_tvout_unmap_resource_mem(reg_mem[j].base, reg_mem[j].res);
1831
1832         return ret;
1833 }
1834
1835 void s5p_hdmi_ctrl_destructor(void)
1836 {
1837         struct s5p_hdmi_ctrl_private_data       *ctrl = &s5p_hdmi_ctrl_private;
1838         struct reg_mem_info             *reg_mem = ctrl->reg_mem;
1839         struct s5p_tvout_clk_info               *clk = ctrl->clk;
1840         struct irq_info                 *irq = &ctrl->irq;
1841
1842         int i;
1843
1844         if (irq->no >= 0)
1845                 free_irq(irq->no, NULL);
1846
1847         for (i = 0; i < HDMI_NO_OF_MEM_RES; i++)
1848                 s5p_tvout_unmap_resource_mem(reg_mem[i].base, reg_mem[i].res);
1849
1850         for (i = HDMI_PCLK; i < HDMI_NO_OF_CLK; i++)
1851                 if (clk[i].ptr) {
1852                         if (ctrl->running)
1853                                 clk_disable(clk[i].ptr);
1854                         clk_put(clk[i].ptr);
1855                 }
1856 }
1857
1858 void s5p_hdmi_ctrl_suspend(void)
1859 {
1860 }
1861
1862 void s5p_hdmi_ctrl_resume(void)
1863 {
1864 }
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874 /****************************************
1875  * Functions for tvif ctrl class
1876  ***************************************/
1877 static void s5p_tvif_ctrl_init_private(void)
1878 {
1879 }
1880
1881 /*
1882  * TV cut off sequence
1883  * VP stop -> Mixer stop -> HDMI stop -> HDMI TG stop
1884  * Above sequence should be satisfied.
1885  */
1886 static int s5p_tvif_ctrl_internal_stop(void)
1887 {
1888         s5p_mixer_ctrl_stop();
1889
1890         switch (s5p_tvif_ctrl_private.curr_if) {
1891         case TVOUT_COMPOSITE:
1892                 s5p_sdo_ctrl_stop();
1893                 break;
1894
1895         case TVOUT_DVI:
1896         case TVOUT_HDMI:
1897         case TVOUT_HDMI_RGB:
1898                 s5p_hdmi_ctrl_stop();
1899                 s5p_hdmi_ctrl_phy_power(0);
1900                 break;
1901
1902         default:
1903                 tvout_err("invalid out parameter(%d)\n",
1904                         s5p_tvif_ctrl_private.curr_if);
1905                 return -1;
1906         }
1907
1908         return 0;
1909 }
1910
1911 static void s5p_tvif_ctrl_internal_start(
1912                 enum s5p_tvout_disp_mode std,
1913                 enum s5p_tvout_o_mode inf)
1914 {
1915         s5p_mixer_ctrl_set_int_enable(false);
1916
1917         /* Clear All Interrupt Pending */
1918         s5p_mixer_ctrl_clear_pend_all();
1919
1920         switch (inf) {
1921         case TVOUT_COMPOSITE:
1922                 if (s5p_mixer_ctrl_start(std, inf) < 0)
1923                         goto ret_on_err;
1924
1925                 if (0 != s5p_sdo_ctrl_start(std))
1926                         goto ret_on_err;
1927
1928                 break;
1929
1930         case TVOUT_HDMI:
1931         case TVOUT_HDMI_RGB:
1932         case TVOUT_DVI:
1933                 s5p_hdmi_ctrl_phy_power(1);
1934
1935                 if (s5p_mixer_ctrl_start(std, inf) < 0)
1936                         goto ret_on_err;
1937
1938                 if (0 != s5p_hdmi_ctrl_start(std, inf))
1939                         goto ret_on_err;
1940                 break;
1941         default:
1942                 break;
1943         }
1944
1945 ret_on_err:
1946         s5p_mixer_ctrl_set_int_enable(true);
1947
1948         /* Clear All Interrupt Pending */
1949         s5p_mixer_ctrl_clear_pend_all();
1950 }
1951
1952 int s5p_tvif_ctrl_set_audio(bool en)
1953 {
1954         switch (s5p_tvif_ctrl_private.curr_if) {
1955         case TVOUT_HDMI:
1956         case TVOUT_HDMI_RGB:
1957         case TVOUT_DVI:
1958                 s5p_hdmi_ctrl_set_audio(en);
1959
1960                 break;
1961         default:
1962                 return -EINVAL;
1963         }
1964
1965         return 0;
1966 }
1967
1968 int s5p_tvif_ctrl_set_av_mute(bool en)
1969 {
1970         switch (s5p_tvif_ctrl_private.curr_if) {
1971         case TVOUT_HDMI:
1972         case TVOUT_HDMI_RGB:
1973         case TVOUT_DVI:
1974                 s5p_hdmi_ctrl_set_av_mute(en);
1975
1976                 break;
1977         default:
1978                 return -EINVAL;
1979         }
1980
1981         return 0;
1982 }
1983
1984 int s5p_tvif_ctrl_get_std_if(
1985                 enum s5p_tvout_disp_mode *std, enum s5p_tvout_o_mode *inf)
1986 {
1987         *std = s5p_tvif_ctrl_private.curr_std;
1988         *inf = s5p_tvif_ctrl_private.curr_if;
1989
1990         return 0;
1991 }
1992
1993 bool s5p_tvif_ctrl_get_run_state()
1994 {
1995         return s5p_tvif_ctrl_private.running;
1996 }
1997
1998 int s5p_tvif_ctrl_start(
1999                 enum s5p_tvout_disp_mode std, enum s5p_tvout_o_mode inf)
2000 {
2001         if (s5p_tvif_ctrl_private.running &&
2002                 (std == s5p_tvif_ctrl_private.curr_std) &&
2003                 (inf == s5p_tvif_ctrl_private.curr_if))
2004                 goto cannot_change;
2005
2006         switch (inf) {
2007         case TVOUT_COMPOSITE:
2008         case TVOUT_HDMI:
2009         case TVOUT_HDMI_RGB:
2010         case TVOUT_DVI:
2011                 break;
2012         default:
2013                 tvout_err("invalid out parameter(%d)\n", inf);
2014                 goto cannot_change;
2015         }
2016
2017         /* how to control the clock path on stop time ??? */
2018         if (s5p_tvif_ctrl_private.running)
2019                 s5p_tvif_ctrl_internal_stop();
2020
2021         s5p_tvif_ctrl_internal_start(std, inf);
2022
2023         s5p_tvif_ctrl_private.running = true;
2024         s5p_tvif_ctrl_private.curr_std = std;
2025         s5p_tvif_ctrl_private.curr_if = inf;
2026
2027         return 0;
2028
2029 cannot_change:
2030         return -1;
2031 }
2032
2033 void s5p_tvif_ctrl_stop(void)
2034 {
2035         if (s5p_tvif_ctrl_private.running) {
2036                 s5p_tvif_ctrl_internal_stop();
2037
2038                 s5p_tvif_ctrl_private.running = false;
2039         }
2040 }
2041
2042 int s5p_tvif_ctrl_constructor(struct platform_device *pdev)
2043 {
2044         if (s5p_sdo_ctrl_constructor(pdev))
2045                 goto err;
2046
2047         if (s5p_hdmi_ctrl_constructor(pdev))
2048                 goto err;
2049
2050         s5p_tvif_ctrl_init_private();
2051
2052         return 0;
2053
2054 err:
2055         return -1;
2056 }
2057
2058 void s5p_tvif_ctrl_destructor(void)
2059 {
2060         s5p_sdo_ctrl_destructor();
2061         s5p_hdmi_ctrl_destructor();
2062 }
2063
2064 void s5p_tvif_ctrl_suspend(void)
2065 {
2066         if (s5p_tvif_ctrl_private.running) {
2067                 s5p_tvif_ctrl_internal_stop();
2068 #ifdef CONFIG_VCM
2069                 s5p_tvout_vcm_deactivate();
2070 #endif
2071         }
2072
2073 }
2074
2075 void s5p_tvif_ctrl_resume(void)
2076 {
2077         if (s5p_tvif_ctrl_private.running) {
2078 #ifdef CONFIG_VCM
2079                 s5p_tvout_vcm_activate();
2080 #endif
2081                 s5p_tvif_ctrl_internal_start(
2082                         s5p_tvif_ctrl_private.curr_std,
2083                         s5p_tvif_ctrl_private.curr_if);
2084         }
2085 }