1 #include <linux/delay.h>
4 #include "rk616_hdmi.h"
5 #include "rk616_hdmi_hw.h"
8 // static char edid_result = 0;
11 static int rk616_hdmi_set_vif(rk_screen * screen,bool connect)
13 rk616_set_vif(g_rk616_hdmi,screen,connect);
17 static int rk616_hdmi_init_pol_set(struct mfd_rk616 * rk616,int pol)
21 ret = rk616->read_dev(rk616,CRU_CFGMISC_CON,&val);
26 ret = rk616->write_dev(rk616,CRU_CFGMISC_CON,&val);
30 static inline void delay100us(void)
36 static void rk616_hdmi_av_mute(bool enable)
38 HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
41 static void rk616_hdmi_sys_power_up(void)
43 HDMIMskReg(SYS_CTRL,m_POWER, v_PWR_ON);
45 static void rk616_hdmi_sys_power_down(void)
47 HDMIMskReg(SYS_CTRL,m_POWER, v_PWR_OFF);
51 static void rk616_hdmi_set_pwr_mode(int mode)
53 if(hdmi->pwr_mode == mode)
55 hdmi_dbg(hdmi->dev,"%s change pwr_mode %d --> %d\n",__FUNCTION__,hdmi->pwr_mode,mode);
58 hdmi_dbg(hdmi->dev,"%s change pwr_mode NORMALpwr_mode = %d, mode = %d\n",__FUNCTION__,hdmi->pwr_mode,mode);
59 rk616_hdmi_sys_power_down();
60 HDMIWrReg(PHY_DRIVER,0xaa);
61 HDMIWrReg(PHY_PRE_EMPHASIS,0x0f);
62 HDMIWrReg(PHY_SYS_CTL,0x2d);
63 HDMIWrReg(PHY_SYS_CTL,0x2c);
64 HDMIWrReg(PHY_SYS_CTL,0x28);
65 HDMIWrReg(PHY_SYS_CTL,0x20);
66 HDMIWrReg(PHY_CHG_PWR,0x0f);
67 HDMIWrReg(0xce, 0x00);
68 HDMIWrReg(0xce, 0x01);
69 rk616_hdmi_av_mute(1);
70 rk616_hdmi_sys_power_up();
73 hdmi_dbg(hdmi->dev,"%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",__FUNCTION__,hdmi->pwr_mode,mode);
74 rk616_hdmi_av_mute(0);
75 rk616_hdmi_sys_power_down();
76 HDMIWrReg(PHY_DRIVER,0x00);
77 HDMIWrReg(PHY_PRE_EMPHASIS,0x00);
78 HDMIWrReg(PHY_CHG_PWR,0x00);
79 HDMIWrReg(PHY_SYS_CTL,0x2f);
82 hdmi_dbg(hdmi->dev,"unkown rk616 hdmi pwr mode %d\n",mode);
84 hdmi->pwr_mode = mode;
88 int rk616_hdmi_detect_hotplug(void)
92 HDMIRdReg(INTERRUPT_STATUS1,&value);
94 HDMIWrReg(INTERRUPT_STATUS1, value);
97 HDMIRdReg(HDMI_STATUS,&value);
99 hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
101 if(value == m_HOTPLUG)
102 return HDMI_HPD_ACTIVED;
104 return HDMI_HPD_INSERT;
106 return HDMI_HPD_REMOVED;
109 #define HDMI_SYS_FREG_CLK 11289600
110 #define HDMI_SCL_RATE (100*1000)
111 #define HDMI_DDC_CONFIG (HDMI_SYS_FREG_CLK>>2)/HDMI_SCL_RATE
112 #define DDC_BUS_FREQ_L 0x4b
113 #define DDC_BUS_FREQ_H 0x4c
114 #define EDID_BLOCK_SIZE 128
116 int rk616_hdmi_read_edid(u8 block, u8 * buf)
123 Offset = EDID_BLOCK_SIZE;
126 printk("EDID DATA (Segment = %d Block = %d Offset = %d):\n", (int) Segment, (int) block, (int) Offset);
127 //set edid fifo first addr
130 //set edid word address 00/80
133 //set edid segment pointer
137 //enable edid interrupt
139 // HDMIWrReg(0xc0, c);
140 //wait edid interrupt
142 //printk("Interrupt generated\n");
144 //ret = HDMIRdReg(0xc1, &c);
145 //printk("Interrupt reg=%x \n",c);
146 //clear EDID interrupt reg
148 //HDMIWrReg(0xc1, c);
149 for(i=0; i <EDID_BLOCK_SIZE;i++){
151 HDMIRdReg( 0x50, &c);
154 printk("\n>>>%d:",i);
160 static void rk616_hdmi_config_avi(unsigned char vic, unsigned char output_color)
163 char info[SIZE_AVI_INFOFRAME];
165 memset(info, 0, SIZE_AVI_INFOFRAME);
166 HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
170 info[3] = info[0] + info[1] + info[2];
171 info[4] = (AVI_COLOR_MODE_RGB << 5);
172 info[5] = (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
177 // Calculate AVI InfoFrame ChecKsum
178 for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
182 info[3] = 0x100 - info[3];
184 for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
185 HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
188 static int rk616_hdmi_config_video(struct hdmi_video_para *vpara)
191 struct fb_videomode *mode;
193 hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
195 hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
198 vpara->output_color = VIDEO_OUTPUT_RGB444;
199 if(hdmi->hdcp_power_off_cb)
200 hdmi->hdcp_power_off_cb();
201 // Diable video and audio output
202 HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
204 // Input video mode is SDR RGB24bit, Data enable signal from external
205 HDMIWrReg(VIDEO_CONTRL1, v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) | v_DE_EXTERNAL);
206 HDMIWrReg(VIDEO_CONTRL2, v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) | (vpara->output_color & 0xFF));
209 HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
211 // Enable or disalbe color space convert
212 if(vpara->input_color != vpara->output_color) {
213 value = v_SOF_DISABLE | v_CSC_ENABLE;
216 value = v_SOF_DISABLE;
217 HDMIWrReg(VIDEO_CONTRL3, value);
221 HDMIWrReg(VIDEO_TIMING_CTL, 0);
222 mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
225 hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
228 hdmi->tmdsclk = mode->pixclock;
230 value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
231 if(mode->sync & FB_SYNC_HOR_HIGH_ACT)
232 value |= v_HSYNC_POLARITY(1);
233 if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
234 value |= v_VSYNC_POLARITY(1);
235 HDMIWrReg(VIDEO_TIMING_CTL, value);
237 value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;
238 HDMIWrReg(VIDEO_EXT_HTOTAL_L, value & 0xFF);
239 HDMIWrReg(VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
241 value = mode->left_margin + mode->right_margin + mode->hsync_len;
242 HDMIWrReg(VIDEO_EXT_HBLANK_L, value & 0xFF);
243 HDMIWrReg(VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
245 value = mode->left_margin + mode->hsync_len;
246 HDMIWrReg(VIDEO_EXT_HDELAY_L, value & 0xFF);
247 HDMIWrReg(VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
249 value = mode->hsync_len;
250 HDMIWrReg(VIDEO_EXT_HDURATION_L, value & 0xFF);
251 HDMIWrReg(VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
253 value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;
254 HDMIWrReg(VIDEO_EXT_VTOTAL_L, value & 0xFF);
255 HDMIWrReg(VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
257 value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
258 HDMIWrReg(VIDEO_EXT_VBLANK, value & 0xFF);
260 if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
263 value = mode->upper_margin + mode->vsync_len;
265 HDMIWrReg(VIDEO_EXT_VDELAY, value & 0xFF);
267 value = mode->vsync_len;
268 HDMIWrReg(VIDEO_EXT_VDURATION, value & 0xFF);
271 if(vpara->output_mode == OUTPUT_HDMI) {
272 rk616_hdmi_config_avi(vpara->vic, vpara->output_color);
273 hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
276 hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__);
280 HDMIWrReg(0xed, 0x0f);
281 HDMIWrReg(0xe7, 0x96);
283 if(hdmi->tmdsclk >= 148500000) {
284 HDMIWrReg(0xed, 0xc);
285 HDMIWrReg(0xe7, 0x78);
288 HDMIWrReg(0xed, 0x3);
289 HDMIWrReg(0xe7, 0x1e);
295 static void rk616_hdmi_config_aai(void)
298 char info[SIZE_AUDIO_INFOFRAME];
300 memset(info, 0, SIZE_AUDIO_INFOFRAME);
306 info[3] = info[0] + info[1] + info[2];
307 for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
310 info[3] = 0x100 - info[3];
312 HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
313 for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
314 HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
317 static int rk616_hdmi_config_audio(struct hdmi_audio *audio)
319 int rate, N, channel, mclk_fs;
321 if(audio->channel < 3)
322 channel = I2S_CHANNEL_1_2;
323 else if(audio->channel < 5)
324 channel = I2S_CHANNEL_3_4;
325 else if(audio->channel < 7)
326 channel = I2S_CHANNEL_5_6;
328 channel = I2S_CHANNEL_7_8;
332 case HDMI_AUDIO_FS_32000:
335 mclk_fs = MCLK_384FS;
337 case HDMI_AUDIO_FS_44100:
340 mclk_fs = MCLK_256FS;
342 case HDMI_AUDIO_FS_48000:
345 mclk_fs = MCLK_256FS;
347 case HDMI_AUDIO_FS_88200:
350 mclk_fs = MCLK_128FS;
352 case HDMI_AUDIO_FS_96000:
355 mclk_fs = MCLK_128FS;
357 case HDMI_AUDIO_FS_176400:
360 mclk_fs = MCLK_128FS;
362 case HDMI_AUDIO_FS_192000:
365 mclk_fs = MCLK_128FS;
368 dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
372 //set_audio source I2S
373 if(HDMI_CODEC_SOURCE_SELECT == INPUT_IIS){
374 HDMIWrReg(AUDIO_CTRL1, 0x00);
375 HDMIWrReg(AUDIO_SAMPLE_RATE, rate);
376 HDMIWrReg(AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel) );
377 HDMIWrReg(AUDIO_I2S_MAP, 0x00);
378 HDMIWrReg(AUDIO_I2S_SWAPS_SPDIF, 0); // no swap
380 HDMIWrReg(AUDIO_CTRL1, 0x08);
381 HDMIWrReg(AUDIO_I2S_SWAPS_SPDIF, 0); // no swap
385 HDMIWrReg(AUDIO_N_H, (N >> 16) & 0x0F);
386 HDMIWrReg(AUDIO_N_M, (N >> 8) & 0xFF);
387 HDMIWrReg(AUDIO_N_L, N & 0xFF);
388 rk616_hdmi_config_aai();
393 void rk616_hdmi_control_output(int enable)
398 if(hdmi->pwr_mode == LOWER_PWR)
399 rk616_hdmi_set_pwr_mode(NORMAL);
400 HDMIRdReg(AV_MUTE,&mutestatus);
401 if(mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
402 HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
404 rk616_hdmi_sys_power_up();
405 rk616_hdmi_sys_power_down();
406 rk616_hdmi_sys_power_up();
407 HDMIWrReg(0xce, 0x00);
409 HDMIWrReg(0xce, 0x01);
412 HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
416 int rk616_hdmi_removed(void)
419 dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
420 rk616_hdmi_set_pwr_mode(LOWER_PWR);
422 return HDMI_ERROR_SUCESS;
426 void rk616_hdmi_work(void)
431 HDMIRdReg(INTERRUPT_STATUS1,&interrupt);
433 HDMIWrReg(INTERRUPT_STATUS1, interrupt);
436 if(interrupt & m_HOTPLUG){
437 if(hdmi->state == HDMI_SLEEP)
438 hdmi->state = WAIT_HOTPLUG;
439 if(hdmi->pwr_mode == LOWER_PWR)
440 rk616_hdmi_set_pwr_mode(NORMAL);
442 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
447 if(hdmi->state == HDMI_SLEEP) {
448 // hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n");
449 rk616_hdmi_set_pwr_mode(LOWER_PWR);
453 if(hdmi->hdcp_irq_cb)
454 hdmi->hdcp_irq_cb(interrupt2);
458 static void rk616_hdmi_reset(void)
463 HDMIMskReg(SYS_CTRL,m_RST_DIGITAL,v_NOT_RST_DIGITAL);
465 HDMIMskReg(SYS_CTRL,m_RST_ANALOG,v_NOT_RST_ANALOG);
467 msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
468 val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON |v_INT_POL_HIGH;
469 HDMIMskReg(SYS_CTRL,msk,val);
470 HDMIWrReg(INTERRUPT_MASK1,m_INT_HOTPLUG);
471 rk616_hdmi_set_pwr_mode(LOWER_PWR);
474 int rk616_hdmi_initial(void)
476 int rc = HDMI_ERROR_SUCESS;
478 hdmi->pwr_mode = NORMAL;
479 hdmi->remove = rk616_hdmi_removed ;
480 hdmi->control_output = rk616_hdmi_control_output;
481 hdmi->config_video = rk616_hdmi_config_video;
482 hdmi->config_audio = rk616_hdmi_config_audio;
483 hdmi->detect_hotplug = rk616_hdmi_detect_hotplug;
484 hdmi->read_edid = rk616_hdmi_read_edid;
485 hdmi->set_vif = rk616_hdmi_set_vif;
489 rk616_hdmi_init_pol_set(g_rk616_hdmi,0);
490 if(hdmi->hdcp_power_on_cb)
491 rc = hdmi->hdcp_power_on_cb();