1 /* linux/drivers/media/video/samsung/tvout/s5p_tvif_ctrl.c
3 * Copyright (c) 2009 Samsung Electronics
4 * http://www.samsung.com/
6 * Tvout ctrl class for Samsung TVOUT driver
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.
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
24 * +----------+ +----------+ ctrl class layer
27 * +-----------------+ +-----------------+
28 * | sdo ctrl class | | hdmi ctrl class |
29 * +-----------------+ +-----------------+
31 * ---------------+-------------------------+------------------------------
33 * +-----------------+ +-----------------+
34 * | hw_if/sdo.c | | hw_if/hdmi.c | hw_if layer
35 * +-----------------+ +-----------------+
37 * ---------------+-------------------------+------------------------------
39 * +-----------------+ +-----------------+
40 * | sdo hardware | | hdmi hardware | Hardware
41 * +-----------------+ +-----------------+
43 ****************************************************************************/
44 #include <linux/clk.h>
45 #include <linux/delay.h>
46 #include <linux/err.h>
48 #ifdef CONFIG_CPU_S5PV210
52 #include "s5p_tvout_common_lib.h"
53 #include "hw_if/hw_if.h"
54 #include "s5p_tvout_ctrl.h"
56 /****************************************
57 * Definitions for sdo ctrl class
58 ***************************************/
65 struct s5p_sdo_vscale_cfg {
66 enum s5p_sdo_level composite_level;
67 enum s5p_sdo_vsync_ratio composite_ratio;
72 enum s5p_sdo_closed_caption_type caption_cvbs;
75 struct s5p_sdo_offset_gain {
80 struct s5p_sdo_delay {
82 u32 offset_video_start;
86 struct s5p_sdo_component_porch {
93 struct s5p_sdo_ch_xtalk_cancellat_coeff {
98 struct s5p_sdo_closed_caption {
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;
118 bool color_sub_carrier_phase_adj;
122 struct s5p_tvout_clk_info clk[SDO_NO_OF_CLK];
124 struct reg_mem_info reg_mem;
127 static struct s5p_sdo_ctrl_private_data s5p_sdo_ctrl_private = {
136 .pow_name = "tv_enc_pd",
145 .color_sub_carrier_phase_adj = false,
149 .caption_cvbs = SDO_INS_OTHERS
159 .offset_video_start = 0xfa,
160 .offset_video_end = 0x00
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
176 .cvbs_color_compen = false,
177 .y_lower_mid = 0x200,
180 .y_upper_mid = 0x200,
202 .copy_permit = SDO_525_COPY_PERMIT,
203 .mv_psp = SDO_525_MV_PSP_OFF,
204 .copy_info = SDO_525_COPY_INFO,
206 .display_ratio = SDO_525_4_3_NORMAL
210 .surround_sound = 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
222 .copy_permit = SDO_525_COPY_PERMIT,
223 .mv_psp = SDO_525_MV_PSP_OFF,
224 .copy_info = SDO_525_COPY_INFO,
226 .display_ratio = SDO_525_4_3_NORMAL
230 .surround_sound = 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
246 /****************************************
247 * Definitions for hdmi ctrl class
248 ***************************************/
250 #define AVI_SAME_WITH_PICTURE_AR (0x1<<3)
264 enum s5p_hdmi_pic_aspect {
265 HDMI_PIC_RATIO_4_3 = 1,
266 HDMI_PIC_RATIO_16_9 = 2
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,
276 enum s5p_hdmi_audio_type {
283 enum s5p_hdmi_v_mode {
308 v1920x1080i_50Hz_1250,
327 struct s5p_hdmi_bluescreen {
334 struct s5p_hdmi_packet {
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;
365 struct s5p_hdmi_color_range {
377 struct s5p_hdmi_audio {
378 enum s5p_hdmi_audio_type type;
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;
393 struct s5p_hdmi_o_params {
394 struct s5p_hdmi_o_trans trans;
395 struct s5p_hdmi_o_reg reg;
398 struct s5p_hdmi_ctrl_private_data {
402 enum s5p_tvout_o_mode out;
403 enum s5p_hdmi_v_mode mode;
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;
418 struct s5p_tvout_clk_info clk[HDMI_NO_OF_CLK];
419 struct reg_mem_info reg_mem[HDMI_NO_OF_MEM_RES];
423 static struct s5p_hdmi_v_format s5p_hdmi_v_fmt[] = {
437 .pixel_clock = ePHY_FREQ_27_027,
463 [v1280x720p_60Hz] = {
476 .pixel_clock = ePHY_FREQ_74_250,
502 [v1920x1080i_60Hz] = {
515 .pixel_clock = ePHY_FREQ_74_250,
541 [v1920x1080p_60Hz] = {
554 .pixel_clock = ePHY_FREQ_148_500,
593 .pixel_clock = ePHY_FREQ_27,
619 [v1280x720p_50Hz] = {
632 .pixel_clock = ePHY_FREQ_74_250,
658 [v1920x1080i_50Hz] = {
671 .pixel_clock = ePHY_FREQ_74_250,
697 [v1920x1080p_50Hz] = {
710 .pixel_clock = ePHY_FREQ_148_500,
736 [v1920x1080p_30Hz] = {
749 .pixel_clock = ePHY_FREQ_74_250,
788 .pixel_clock = ePHY_FREQ_27,
814 [v1280x720p_59Hz] = {
827 .pixel_clock = ePHY_FREQ_74_176,
853 [v1920x1080i_59Hz] = {
866 .pixel_clock = ePHY_FREQ_74_176,
892 [v1920x1080p_59Hz] = {
905 .pixel_clock = ePHY_FREQ_148_352,
932 static struct s5p_hdmi_o_params s5p_hdmi_output[] = {
934 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
935 {0x00, 0x00, 0x00, 0x00, 0x00},
937 {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04},
938 {0x40, 0x00, 0x02, 0x00, 0x00},
940 {0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04},
941 {0x00, 0x00, 0x02, 0x20, 0x00},
943 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
944 {0x00, 0x22, 0x01, 0x20, 0x01},
948 static struct s5p_hdmi_ctrl_private_data s5p_hdmi_ctrl_private = {
950 .product = "S5PC210",
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},
978 .correction_en = false,
985 .type = HDMI_60958_AUDIO,
993 .pow_name = "hdmi_pd",
1001 .name = "sclk_hdmi",
1011 .reg_mem[HDMI_PHY] = {
1012 .name = "s5p-i2c-hdmi-phy",
1019 .handler = s5p_hdmi_irq,
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;
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,
1056 /****************************************
1057 * Functions for sdo ctrl class
1058 ***************************************/
1060 static void s5p_sdo_ctrl_init_private(void)
1064 static int s5p_sdo_ctrl_set_reg(enum s5p_tvout_disp_mode disp_mode)
1066 struct s5p_sdo_ctrl_private_data *private = &s5p_sdo_ctrl_private;
1068 s5p_sdo_sw_reset(1);
1070 if (s5p_sdo_set_display_mode(disp_mode, SDO_O_ORDER_COMPOSITE_Y_C_CVBS))
1073 if (s5p_sdo_set_video_scale_cfg(
1074 private->video_scale_cfg.composite_level,
1075 private->video_scale_cfg.composite_ratio))
1078 if (s5p_sdo_set_vbi(
1079 private->vbi.wss_cvbs, private->vbi.caption_cvbs))
1082 s5p_sdo_set_offset_gain(
1083 private->offset_gain.offset, private->offset_gain.gain);
1086 private->delay.delay_y,
1087 private->delay.offset_video_start,
1088 private->delay.offset_video_end);
1090 s5p_sdo_set_schlock(private->color_sub_carrier_phase_adj);
1092 s5p_sdo_set_brightness_hue_saturation(private->bri_hue_sat);
1094 s5p_sdo_set_cvbs_color_compensation(private->cvbs_compen);
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);
1102 s5p_sdo_set_ch_xtalk_cancel_coef(
1103 private->xtalk_cc.coeff2, private->xtalk_cc.coeff1);
1105 s5p_sdo_set_closed_caption(
1106 private->closed_cap.display_cc,
1107 private->closed_cap.nondisplay_cc);
1109 if (s5p_sdo_set_wss525_data(private->wss_525))
1112 if (s5p_sdo_set_wss625_data(private->wss_625))
1115 if (s5p_sdo_set_cgmsa525_data(private->cgms_525))
1118 if (s5p_sdo_set_cgmsa625_data(private->cgms_625))
1121 s5p_sdo_set_interrupt_enable(0);
1123 s5p_sdo_clear_interrupt_pending();
1125 s5p_sdo_clock_on(1);
1131 static void s5p_sdo_ctrl_internal_stop(void)
1133 s5p_sdo_clock_on(0);
1137 static void s5p_sdo_ctrl_clock(bool on)
1140 clk_enable(s5p_sdo_ctrl_private.clk[SDO_MUX].ptr);
1142 #ifdef CONFIG_CPU_S5PV210
1143 s5pv210_pd_enable(s5p_sdo_ctrl_private.pow_name);
1146 #ifdef CONFIG_CPU_S5PV310
1147 s5p_tvout_pm_runtime_get();
1150 clk_enable(s5p_sdo_ctrl_private.clk[SDO_PCLK].ptr);
1152 clk_disable(s5p_sdo_ctrl_private.clk[SDO_PCLK].ptr);
1154 #ifdef CONFIG_CPU_S5PV210
1155 s5pv210_pd_disable(s5p_sdo_ctrl_private.pow_name);
1158 #ifdef CONFIG_CPU_S5PV310
1159 s5p_tvout_pm_runtime_put();
1162 clk_disable(s5p_sdo_ctrl_private.clk[SDO_MUX].ptr);
1168 void s5p_sdo_ctrl_stop(void)
1170 if (s5p_sdo_ctrl_private.running) {
1171 s5p_sdo_ctrl_internal_stop();
1172 s5p_sdo_ctrl_clock(0);
1174 s5p_sdo_ctrl_private.running = false;
1178 int s5p_sdo_ctrl_start(enum s5p_tvout_disp_mode disp_mode)
1180 struct s5p_sdo_ctrl_private_data *sdo_private = &s5p_sdo_ctrl_private;
1182 switch (disp_mode) {
1184 case TVOUT_NTSC_443:
1185 sdo_private->video_scale_cfg.composite_level =
1187 sdo_private->video_scale_cfg.composite_ratio =
1188 SDO_VTOS_RATIO_10_4;
1191 case TVOUT_PAL_BDGHI:
1196 sdo_private->video_scale_cfg.composite_level =
1198 sdo_private->video_scale_cfg.composite_ratio =
1203 tvout_err("invalid disp_mode(%d) for SDO\n",
1205 goto err_on_s5p_sdo_start;
1208 if (sdo_private->running)
1209 s5p_sdo_ctrl_internal_stop();
1211 s5p_sdo_ctrl_clock(1);
1213 sdo_private->running = true;
1216 if (s5p_sdo_ctrl_set_reg(disp_mode))
1217 goto err_on_s5p_sdo_start;
1221 err_on_s5p_sdo_start:
1225 int s5p_sdo_ctrl_constructor(struct platform_device *pdev)
1230 ret = s5p_tvout_map_resource_mem(
1232 s5p_sdo_ctrl_private.reg_mem.name,
1233 &(s5p_sdo_ctrl_private.reg_mem.base),
1234 &(s5p_sdo_ctrl_private.reg_mem.res));
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);
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);
1251 s5p_sdo_ctrl_init_private();
1252 s5p_sdo_init(s5p_sdo_ctrl_private.reg_mem.base);
1257 for (j = 0; j < i; j++)
1258 clk_put(s5p_sdo_ctrl_private.clk[j].ptr);
1260 s5p_tvout_unmap_resource_mem(
1261 s5p_sdo_ctrl_private.reg_mem.base,
1262 s5p_sdo_ctrl_private.reg_mem.res);
1268 void s5p_sdo_ctrl_destructor(void)
1272 s5p_tvout_unmap_resource_mem(
1273 s5p_sdo_ctrl_private.reg_mem.base,
1274 s5p_sdo_ctrl_private.reg_mem.res);
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);
1289 /****************************************
1290 * Functions for hdmi ctrl class
1291 ***************************************/
1293 static enum s5p_hdmi_v_mode s5p_hdmi_check_v_fmt(enum s5p_tvout_disp_mode disp)
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;
1299 video->aspect = HDMI_PIC_RATIO_16_9;
1300 video->colorimetry = HDMI_CLRIMETRY_601;
1303 case TVOUT_480P_60_16_9:
1304 mode = v720x480p_60Hz;
1307 case TVOUT_480P_60_4_3:
1308 mode = v720x480p_60Hz;
1309 video->aspect = HDMI_PIC_RATIO_4_3;
1313 mode = v720x480p_59Hz;
1316 case TVOUT_576P_50_16_9:
1317 mode = v720x576p_50Hz;
1320 case TVOUT_576P_50_4_3:
1321 mode = v720x576p_50Hz;
1322 video->aspect = HDMI_PIC_RATIO_4_3;
1326 mode = v1280x720p_60Hz;
1327 video->colorimetry = HDMI_CLRIMETRY_709;
1331 mode = v1280x720p_59Hz;
1332 video->colorimetry = HDMI_CLRIMETRY_709;
1336 mode = v1280x720p_50Hz;
1337 video->colorimetry = HDMI_CLRIMETRY_709;
1340 case TVOUT_1080P_30:
1341 mode = v1920x1080p_30Hz;
1342 video->colorimetry = HDMI_CLRIMETRY_709;
1345 case TVOUT_1080P_60:
1346 mode = v1920x1080p_60Hz;
1347 video->colorimetry = HDMI_CLRIMETRY_709;
1350 case TVOUT_1080P_59:
1351 mode = v1920x1080p_59Hz;
1352 video->colorimetry = HDMI_CLRIMETRY_709;
1355 case TVOUT_1080P_50:
1356 mode = v1920x1080p_50Hz;
1357 video->colorimetry = HDMI_CLRIMETRY_709;
1360 case TVOUT_1080I_60:
1361 mode = v1920x1080i_60Hz;
1362 video->colorimetry = HDMI_CLRIMETRY_709;
1365 case TVOUT_1080I_59:
1366 mode = v1920x1080i_59Hz;
1367 video->colorimetry = HDMI_CLRIMETRY_709;
1370 case TVOUT_1080I_50:
1371 mode = v1920x1080i_50Hz;
1372 video->colorimetry = HDMI_CLRIMETRY_709;
1376 mode = v720x480p_60Hz;
1377 tvout_err("Not supported mode : %d\n", mode);
1383 static void s5p_hdmi_set_acr(struct s5p_hdmi_audio *audio, u8 *acr)
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;
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;
1402 acr[2] = cts >> 8 & 0xff;
1403 acr[3] = cts & 0xff;
1406 acr[5] = n >> 8 & 0xff;
1409 tvout_dbg("n value = %d\n", n);
1410 tvout_dbg("cts = %d\n", cts);
1413 static void s5p_hdmi_set_asp(u8 *header)
1419 static void s5p_hdmi_set_acp(struct s5p_hdmi_audio *audio, u8 *header)
1421 header[1] = audio->type;
1424 static void s5p_hdmi_set_isrc(u8 *header)
1428 static void s5p_hdmi_set_gmp(u8 *gmp)
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)
1436 struct s5p_hdmi_o_params param = s5p_hdmi_output[out];
1437 struct s5p_hdmi_v_frame frame;
1439 frame = s5p_hdmi_v_fmt[mode].frame;
1441 avi[0] = param.reg.pxl_fmt;
1442 avi[0] |= (0x1 << 4);
1444 avi[1] = video->colorimetry;
1445 avi[1] |= video->aspect << 4;
1446 avi[1] |= AVI_SAME_WITH_PICTURE_AR;
1448 avi[3] = (video->aspect == HDMI_PIC_RATIO_16_9) ?
1449 frame.vic_16_9 : frame.vic;
1451 avi[4] = frame.repetition;
1454 static void s5p_hdmi_set_aui(struct s5p_hdmi_audio *audio, u8 *aui)
1456 aui[0] = (0 << 4) | audio->channel;
1457 aui[1] = ((audio->type == HDMI_60958_AUDIO) ? 0 : audio->freq << 2) | 0;
1461 static void s5p_hdmi_set_spd(u8 *spd)
1463 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1465 memcpy(spd, ctrl->vendor, 8);
1466 memcpy(&spd[8], ctrl->product, 16);
1468 spd[24] = 0x1; /* Digital STB */
1471 static void s5p_hdmi_set_mpg(u8 *mpg)
1475 static int s5p_hdmi_ctrl_audio_enable(bool en)
1477 if (!s5p_hdmi_output[s5p_hdmi_ctrl_private.out].reg.dvi)
1478 s5p_hdmi_reg_audio_enable(en);
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)
1486 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1488 ctrl->blue_screen.cb_b = cb_b;
1489 ctrl->blue_screen.y_g = y_g;
1490 ctrl->blue_screen.cr_r = cr_r;
1492 s5p_hdmi_reg_bluescreen_clr(cb_b, y_g, cr_r);
1496 static void s5p_hdmi_ctrl_set_bluescreen(bool en)
1498 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1500 ctrl->blue_screen.enable = en ? true : false;
1502 s5p_hdmi_reg_bluescreen(en);
1505 static void s5p_hdmi_ctrl_set_audio(bool en)
1507 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1509 s5p_hdmi_ctrl_private.audio.on = en ? 1 : 0;
1512 s5p_hdmi_ctrl_audio_enable(en);
1515 static void s5p_hdmi_ctrl_set_av_mute(bool en)
1517 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1519 ctrl->av_mute = en ? 1 : 0;
1521 if (ctrl->running) {
1523 s5p_hdmi_ctrl_audio_enable(false);
1524 s5p_hdmi_ctrl_set_bluescreen(true);
1526 s5p_hdmi_ctrl_audio_enable(true);
1527 s5p_hdmi_ctrl_set_bluescreen(false);
1533 u8 s5p_hdmi_ctrl_get_mute(void)
1535 return s5p_hdmi_ctrl_private.av_mute ? 1 : 0;
1538 #if 0 /* This function will be used in the future */
1539 static void s5p_hdmi_ctrl_mute(bool en)
1541 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1544 s5p_hdmi_reg_bluescreen(true);
1545 s5p_hdmi_ctrl_audio_enable(false);
1547 s5p_hdmi_reg_bluescreen(false);
1549 s5p_hdmi_ctrl_audio_enable(true);
1554 void s5p_hdmi_ctrl_set_hdcp(bool en)
1556 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1558 ctrl->hdcp_en = en ? 1 : 0;
1561 static void s5p_hdmi_ctrl_init_private(void)
1565 static bool s5p_hdmi_ctrl_set_reg(
1566 enum s5p_hdmi_v_mode mode, enum s5p_tvout_o_mode out)
1568 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1569 struct s5p_hdmi_packet *packet = &ctrl->packet;
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;
1575 s5p_hdmi_reg_bluescreen_clr(bl->cb_b, bl->y_g, bl->cr_r);
1576 s5p_hdmi_reg_bluescreen(bl->enable);
1578 s5p_hdmi_reg_clr_range(cr->y_min, cr->y_max, cr->c_min, cr->c_max);
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);
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);
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);
1593 s5p_hdmi_reg_packet_trans(&s5p_hdmi_output[out].trans);
1594 s5p_hdmi_reg_output(&s5p_hdmi_output[out].reg);
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);
1600 switch (ctrl->audio.type) {
1601 case HDMI_GENERIC_AUDIO:
1604 case HDMI_60958_AUDIO:
1605 s5p_hdmi_audio_init(PCM, 44100, 16, 0);
1608 case HDMI_DVD_AUDIO:
1609 case HDMI_SUPER_AUDIO:
1613 tvout_err("Invalid audio type %d\n", ctrl->audio.type);
1617 s5p_hdmi_reg_audio_enable(true);
1622 static void s5p_hdmi_ctrl_internal_stop(void)
1624 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1625 struct s5p_hdmi_tg *tg = &ctrl->tg;
1627 #ifdef CONFIG_HDMI_HPD
1635 s5p_hdmi_reg_enable(false);
1637 s5p_hdmi_reg_tg_cmd(tg->correction_en, tg->bt656_en, false);
1640 int s5p_hdmi_ctrl_phy_power(bool on)
1644 clk_enable(s5ptv_status.i2c_phy_clk);
1646 s5p_hdmi_phy_power(true);
1651 * for preventing hdmi hang up when restart
1652 * switch to internal clk - SCLK_DAC, SCLK_PIXEL
1654 s5p_mixer_ctrl_mux_clk(s5ptv_status.sclk_dac);
1655 clk_set_parent(s5ptv_status.sclk_hdmi,
1656 s5ptv_status.sclk_pixel);
1658 s5p_hdmi_phy_power(false);
1660 clk_disable(s5ptv_status.i2c_phy_clk);
1666 static void s5p_hdmi_ctrl_clock(bool on)
1668 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1669 struct s5p_tvout_clk_info *clk = ctrl->clk;
1672 clk_enable(clk[HDMI_MUX].ptr);
1674 #ifdef CONFIG_CPU_S5PV210
1675 s5pv210_pd_enable(ctrl->pow_name);
1678 #ifdef CONFIG_CPU_S5PV310
1679 s5p_tvout_pm_runtime_get();
1682 clk_enable(clk[HDMI_PCLK].ptr);
1684 clk_disable(clk[HDMI_PCLK].ptr);
1686 #ifdef CONFIG_CPU_S5PV210
1687 s5pv210_pd_disable(ctrl->pow_name);
1690 #ifdef CONFIG_CPU_S5PV310
1691 s5p_tvout_pm_runtime_put();
1694 clk_disable(clk[HDMI_MUX].ptr);
1700 void s5p_hdmi_ctrl_stop(void)
1702 struct s5p_hdmi_ctrl_private_data *ctrl = &s5p_hdmi_ctrl_private;
1704 if (ctrl->running) {
1705 s5p_hdmi_ctrl_internal_stop();
1706 s5p_hdmi_ctrl_clock(0);
1708 ctrl->running = false;
1712 int s5p_hdmi_ctrl_start(
1713 enum s5p_tvout_disp_mode disp, enum s5p_tvout_o_mode out)
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;
1719 enum s5p_hdmi_v_mode mode;
1722 mode = s5p_hdmi_check_v_fmt(disp);
1726 s5p_hdmi_ctrl_internal_stop();
1728 s5p_hdmi_ctrl_clock(1);
1729 ctrl->running = true;
1732 #ifdef CONFIG_HDMI_HPD
1733 s5p_hpd_set_hdmiint();
1736 frame = s5p_hdmi_v_fmt[mode].frame;
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;
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);
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);
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);
1757 s5p_hdmi_ctrl_set_reg(mode, out);
1759 s5p_hdmi_reg_enable(true);
1766 err_on_s5p_hdmi_start:
1770 int s5p_hdmi_ctrl_constructor(struct platform_device *pdev)
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;
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));
1786 for (k = HDMI_PCLK; k < HDMI_NO_OF_CLK; k++) {
1787 clk[k].ptr = clk_get(&pdev->dev, clk[k].name);
1789 if (IS_ERR(clk[k].ptr)) {
1790 printk(KERN_ERR "%s clk is not found\n", clk[k].name);
1796 irq->no = platform_get_irq_byname(pdev, irq->name);
1799 printk(KERN_ERR "can not get platform irq by name : %s\n",
1805 ret = request_irq(irq->no, irq->handler, IRQF_DISABLED,
1808 printk(KERN_ERR "can not request irq : %s\n", irq->name);
1812 s5p_hdmi_ctrl_init_private();
1813 s5p_hdmi_init(reg_mem[HDMI].base, reg_mem[HDMI_PHY].base);
1815 /* set initial state of HDMI PHY power to off */
1816 s5p_hdmi_ctrl_phy_power(1);
1817 s5p_hdmi_ctrl_phy_power(0);
1825 for (j = 0; j < k; j++)
1826 clk_put(clk[j].ptr);
1829 for (j = 0; j < i; j++)
1830 s5p_tvout_unmap_resource_mem(reg_mem[j].base, reg_mem[j].res);
1835 void s5p_hdmi_ctrl_destructor(void)
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;
1845 free_irq(irq->no, NULL);
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);
1850 for (i = HDMI_PCLK; i < HDMI_NO_OF_CLK; i++)
1853 clk_disable(clk[i].ptr);
1854 clk_put(clk[i].ptr);
1858 void s5p_hdmi_ctrl_suspend(void)
1862 void s5p_hdmi_ctrl_resume(void)
1874 /****************************************
1875 * Functions for tvif ctrl class
1876 ***************************************/
1877 static void s5p_tvif_ctrl_init_private(void)
1882 * TV cut off sequence
1883 * VP stop -> Mixer stop -> HDMI stop -> HDMI TG stop
1884 * Above sequence should be satisfied.
1886 static int s5p_tvif_ctrl_internal_stop(void)
1888 s5p_mixer_ctrl_stop();
1890 switch (s5p_tvif_ctrl_private.curr_if) {
1891 case TVOUT_COMPOSITE:
1892 s5p_sdo_ctrl_stop();
1897 case TVOUT_HDMI_RGB:
1898 s5p_hdmi_ctrl_stop();
1899 s5p_hdmi_ctrl_phy_power(0);
1903 tvout_err("invalid out parameter(%d)\n",
1904 s5p_tvif_ctrl_private.curr_if);
1911 static void s5p_tvif_ctrl_internal_start(
1912 enum s5p_tvout_disp_mode std,
1913 enum s5p_tvout_o_mode inf)
1915 s5p_mixer_ctrl_set_int_enable(false);
1917 /* Clear All Interrupt Pending */
1918 s5p_mixer_ctrl_clear_pend_all();
1921 case TVOUT_COMPOSITE:
1922 if (s5p_mixer_ctrl_start(std, inf) < 0)
1925 if (0 != s5p_sdo_ctrl_start(std))
1931 case TVOUT_HDMI_RGB:
1933 s5p_hdmi_ctrl_phy_power(1);
1935 if (s5p_mixer_ctrl_start(std, inf) < 0)
1938 if (0 != s5p_hdmi_ctrl_start(std, inf))
1946 s5p_mixer_ctrl_set_int_enable(true);
1948 /* Clear All Interrupt Pending */
1949 s5p_mixer_ctrl_clear_pend_all();
1952 int s5p_tvif_ctrl_set_audio(bool en)
1954 switch (s5p_tvif_ctrl_private.curr_if) {
1956 case TVOUT_HDMI_RGB:
1958 s5p_hdmi_ctrl_set_audio(en);
1968 int s5p_tvif_ctrl_set_av_mute(bool en)
1970 switch (s5p_tvif_ctrl_private.curr_if) {
1972 case TVOUT_HDMI_RGB:
1974 s5p_hdmi_ctrl_set_av_mute(en);
1984 int s5p_tvif_ctrl_get_std_if(
1985 enum s5p_tvout_disp_mode *std, enum s5p_tvout_o_mode *inf)
1987 *std = s5p_tvif_ctrl_private.curr_std;
1988 *inf = s5p_tvif_ctrl_private.curr_if;
1993 bool s5p_tvif_ctrl_get_run_state()
1995 return s5p_tvif_ctrl_private.running;
1998 int s5p_tvif_ctrl_start(
1999 enum s5p_tvout_disp_mode std, enum s5p_tvout_o_mode inf)
2001 if (s5p_tvif_ctrl_private.running &&
2002 (std == s5p_tvif_ctrl_private.curr_std) &&
2003 (inf == s5p_tvif_ctrl_private.curr_if))
2007 case TVOUT_COMPOSITE:
2009 case TVOUT_HDMI_RGB:
2013 tvout_err("invalid out parameter(%d)\n", inf);
2017 /* how to control the clock path on stop time ??? */
2018 if (s5p_tvif_ctrl_private.running)
2019 s5p_tvif_ctrl_internal_stop();
2021 s5p_tvif_ctrl_internal_start(std, inf);
2023 s5p_tvif_ctrl_private.running = true;
2024 s5p_tvif_ctrl_private.curr_std = std;
2025 s5p_tvif_ctrl_private.curr_if = inf;
2033 void s5p_tvif_ctrl_stop(void)
2035 if (s5p_tvif_ctrl_private.running) {
2036 s5p_tvif_ctrl_internal_stop();
2038 s5p_tvif_ctrl_private.running = false;
2042 int s5p_tvif_ctrl_constructor(struct platform_device *pdev)
2044 if (s5p_sdo_ctrl_constructor(pdev))
2047 if (s5p_hdmi_ctrl_constructor(pdev))
2050 s5p_tvif_ctrl_init_private();
2058 void s5p_tvif_ctrl_destructor(void)
2060 s5p_sdo_ctrl_destructor();
2061 s5p_hdmi_ctrl_destructor();
2064 void s5p_tvif_ctrl_suspend(void)
2066 if (s5p_tvif_ctrl_private.running) {
2067 s5p_tvif_ctrl_internal_stop();
2069 s5p_tvout_vcm_deactivate();
2075 void s5p_tvif_ctrl_resume(void)
2077 if (s5p_tvif_ctrl_private.running) {
2079 s5p_tvout_vcm_activate();
2081 s5p_tvif_ctrl_internal_start(
2082 s5p_tvif_ctrl_private.curr_std,
2083 s5p_tvif_ctrl_private.curr_if);