hdmi: rk616: set hdmi pll(n = 15, m = 150) modify shiny on some tv
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / chips / rk616 / rk616_hdmi_hw.c
1 #include <linux/delay.h>
2 #include <asm/io.h>
3 #include <mach/io.h>
4 #include "rk616_hdmi.h"
5 #include "rk616_hdmi_hw.h"
6 #include <mach/gpio.h>
7
8 // static char edid_result = 0;
9
10
11 static int rk616_hdmi_set_vif(rk_screen * screen,bool connect)
12 {
13         rk616_set_vif(g_rk616_hdmi,screen,connect);
14         return 0;
15 }
16
17 static int rk616_hdmi_init_pol_set(struct mfd_rk616 * rk616,int pol)
18 {
19         u32 val;
20         int ret;
21         ret = rk616->read_dev(rk616,CRU_CFGMISC_CON,&val);
22         if(pol)
23                 val &= 0xffffffdf;
24         else
25                 val |= 0x20;
26         ret = rk616->write_dev(rk616,CRU_CFGMISC_CON,&val);
27
28         return 0;
29 }
30 static inline void delay100us(void)
31 {
32         msleep(1);
33 }
34
35
36 static void rk616_hdmi_av_mute(bool enable)
37 {
38         HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
39 }
40
41 static void rk616_hdmi_sys_power_up(void)
42 {
43         HDMIMskReg(SYS_CTRL,m_POWER, v_PWR_ON);
44 }
45 static void rk616_hdmi_sys_power_down(void)
46 {
47         HDMIMskReg(SYS_CTRL,m_POWER, v_PWR_OFF);
48 }
49
50
51 static void rk616_hdmi_set_pwr_mode(int mode)
52 {
53         if(hdmi->pwr_mode == mode)
54                 return; 
55         hdmi_dbg(hdmi->dev,"%s change pwr_mode %d --> %d\n",__FUNCTION__,hdmi->pwr_mode,mode);
56     switch(mode){
57      case NORMAL:
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();
71                 break;
72         case LOWER_PWR:
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);
80                 break;
81         default:
82             hdmi_dbg(hdmi->dev,"unkown rk616 hdmi pwr mode %d\n",mode);
83     }
84         hdmi->pwr_mode = mode;
85 }
86
87
88 int rk616_hdmi_detect_hotplug(void)
89 {
90         int value = 0;
91 #if 0
92         HDMIRdReg(INTERRUPT_STATUS1,&value);
93         if(value){
94                 HDMIWrReg(INTERRUPT_STATUS1, value);
95         }
96 #endif
97         HDMIRdReg(HDMI_STATUS,&value);
98         
99         hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
100         value &= m_HOTPLUG;
101         if(value == m_HOTPLUG)
102                 return HDMI_HPD_ACTIVED;
103         else if(value)
104                 return HDMI_HPD_INSERT;
105         else
106                 return HDMI_HPD_REMOVED;
107 }
108
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
115
116 int rk616_hdmi_read_edid(u8 block, u8 * buf)
117 {
118         u32 c = 0;
119         int ret = 0,i;
120         u8 Segment = 0;
121         u8 Offset = 0;
122         if(block%2)
123                 Offset = EDID_BLOCK_SIZE;
124         if(block/2)
125                 Segment = 1;
126         printk("EDID DATA (Segment = %d Block = %d Offset = %d):\n", (int) Segment, (int) block, (int) Offset);
127         //set edid fifo first addr
128         c = 0x00;
129         HDMIWrReg(0x4f,0);
130         //set edid word address 00/80
131         c = Offset;
132         HDMIWrReg(0x4e, c);
133         //set edid segment pointer
134         c = Segment;
135         HDMIWrReg(0x4d, c);
136
137         //enable edid interrupt
138 //      c=0xc6;
139 //      HDMIWrReg(0xc0, c);
140         //wait edid interrupt
141         msleep(10);
142         //printk("Interrupt generated\n");
143         //c=0x00;
144         //ret = HDMIRdReg(0xc1, &c);
145         //printk("Interrupt reg=%x \n",c);
146         //clear EDID interrupt reg
147         //c=0x04;
148         //HDMIWrReg(0xc1, c);
149         for(i=0; i <EDID_BLOCK_SIZE;i++){
150                 c = 0;      
151                 HDMIRdReg( 0x50, &c);
152                 buf[i] = c;
153                 if(i%16==0)
154                         printk("\n>>>%d:",i);
155                 printk("%02x ",c);
156         }
157         return ret;
158 }
159
160 static void rk616_hdmi_config_avi(unsigned char vic, unsigned char output_color)
161 {
162         int i;
163         char info[SIZE_AVI_INFOFRAME];
164         
165         memset(info, 0, SIZE_AVI_INFOFRAME);
166         HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
167         info[0] = 0x82;
168         info[1] = 0x02;
169         info[2] = 0x0D; 
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;
173         info[6] = 0;
174         info[7] = vic;
175         info[8] = 0;
176
177         // Calculate AVI InfoFrame ChecKsum
178         for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
179         {
180         info[3] += info[i];
181         }
182         info[3] = 0x100 - info[3];
183         
184         for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
185                 HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
186 }
187
188 static int rk616_hdmi_config_video(struct hdmi_video_para *vpara)
189 {
190         int value;
191         struct fb_videomode *mode;
192         
193         hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
194         if(vpara == NULL) {
195                 hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
196                 return -1;
197         }
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));
203         
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));
207
208         // Set HDMI Mode
209         HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
210
211         // Enable or disalbe color space convert
212         if(vpara->input_color != vpara->output_color) {
213                 value = v_SOF_DISABLE | v_CSC_ENABLE;
214         }
215         else
216                 value = v_SOF_DISABLE;
217         HDMIWrReg(VIDEO_CONTRL3, value);
218
219         // Set ext video
220 #if 1
221         HDMIWrReg(VIDEO_TIMING_CTL, 0);
222         mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
223         if(mode == NULL)
224         {
225                 hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
226                 return -ENOENT;
227         }
228         hdmi->tmdsclk = mode->pixclock;
229 #else
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);
236         
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);
240         
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);
244         
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);
248         
249         value = mode->hsync_len;
250         HDMIWrReg(VIDEO_EXT_HDURATION_L, value & 0xFF);
251         HDMIWrReg(VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
252         
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);
256         
257         value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
258         HDMIWrReg(VIDEO_EXT_VBLANK, value & 0xFF);
259
260         if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
261                 value = 42;
262         else
263                 value = mode->upper_margin + mode->vsync_len;
264
265         HDMIWrReg(VIDEO_EXT_VDELAY, value & 0xFF);
266         
267         value = mode->vsync_len;
268         HDMIWrReg(VIDEO_EXT_VDURATION, value & 0xFF);
269 #endif
270         
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__);
274         }
275         else {
276                 hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); 
277         }
278         
279 #if 1
280         HDMIWrReg(0xed, 0x0f);
281         HDMIWrReg(0xe7, 0x96);
282 #else
283         if(hdmi->tmdsclk >= 148500000) {
284                 HDMIWrReg(0xed, 0xc);
285                 HDMIWrReg(0xe7, 0x78);
286         }
287         else {
288                 HDMIWrReg(0xed, 0x3);
289                 HDMIWrReg(0xe7, 0x1e);
290         }
291 #endif
292         return 0;
293 }
294
295 static void rk616_hdmi_config_aai(void)
296 {
297         int i;
298         char info[SIZE_AUDIO_INFOFRAME];
299         
300         memset(info, 0, SIZE_AUDIO_INFOFRAME);
301         
302         info[0] = 0x84;
303         info[1] = 0x01;
304         info[2] = 0x0A;
305         
306         info[3] = info[0] + info[1] + info[2];  
307         for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
308         info[3] += info[i];
309         
310         info[3] = 0x100 - info[3];
311         
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]);
315 }
316
317 static int rk616_hdmi_config_audio(struct hdmi_audio *audio)
318 {
319         int rate, N, channel, mclk_fs;
320         
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;
327         else
328                 channel = I2S_CHANNEL_7_8;
329                 
330         switch(audio->rate)
331         {
332                 case HDMI_AUDIO_FS_32000:
333                         rate = AUDIO_32K;
334                         N = N_32K;
335                         mclk_fs = MCLK_384FS;
336                         break;
337                 case HDMI_AUDIO_FS_44100:
338                         rate = AUDIO_441K;
339                         N = N_441K;
340                         mclk_fs = MCLK_256FS;
341                         break;
342                 case HDMI_AUDIO_FS_48000:
343                         rate = AUDIO_48K;
344                         N = N_48K;
345                         mclk_fs = MCLK_256FS;
346                         break;
347                 case HDMI_AUDIO_FS_88200:
348                         rate = AUDIO_882K;
349                         N = N_882K;
350                         mclk_fs = MCLK_128FS;
351                         break;
352                 case HDMI_AUDIO_FS_96000:
353                         rate = AUDIO_96K;
354                         N = N_96K;
355                         mclk_fs = MCLK_128FS;
356                         break;
357                 case HDMI_AUDIO_FS_176400:
358                         rate = AUDIO_1764K;
359                         N = N_1764K;
360                         mclk_fs = MCLK_128FS;
361                         break;
362                 case HDMI_AUDIO_FS_192000:
363                         rate = AUDIO_192K;
364                         N = N_192K;
365                         mclk_fs = MCLK_128FS;
366                         break;
367                 default:
368                         dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
369                         return -ENOENT;
370         }
371
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 
379         }else{
380                 HDMIWrReg(AUDIO_CTRL1, 0x08);
381                 HDMIWrReg(AUDIO_I2S_SWAPS_SPDIF, 0); // no swap 
382         }
383                 
384     //Set N value
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();
389     
390     return 0;
391 }
392
393 void rk616_hdmi_control_output(int enable)
394 {
395         char mutestatus = 0;
396         
397         if(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));
403                 }
404                 rk616_hdmi_sys_power_up();
405                 rk616_hdmi_sys_power_down();
406                 rk616_hdmi_sys_power_up();
407                 HDMIWrReg(0xce, 0x00);
408                 delay100us();
409                 HDMIWrReg(0xce, 0x01);
410         }
411         else {
412                 HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
413         }
414 }
415
416 int rk616_hdmi_removed(void)
417 {
418
419         dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
420         rk616_hdmi_set_pwr_mode(LOWER_PWR);
421
422         return HDMI_ERROR_SUCESS;
423 }
424
425
426 void rk616_hdmi_work(void)
427 {               
428         u32 interrupt = 0;
429         int value = 0;
430
431         HDMIRdReg(INTERRUPT_STATUS1,&interrupt);
432         if(interrupt){
433                 HDMIWrReg(INTERRUPT_STATUS1, interrupt);
434         }
435
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);
441
442                 queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
443
444         }
445
446 #if 0   
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);
450         }
451 #endif
452 #if 0
453         if(hdmi->hdcp_irq_cb)
454                 hdmi->hdcp_irq_cb(interrupt2);
455 #endif
456 }
457
458 static void rk616_hdmi_reset(void)
459 {
460         u32 val = 0;
461         u32 msk = 0;
462         
463         HDMIMskReg(SYS_CTRL,m_RST_DIGITAL,v_NOT_RST_DIGITAL);
464         delay100us();
465         HDMIMskReg(SYS_CTRL,m_RST_ANALOG,v_NOT_RST_ANALOG);             
466         delay100us();
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);
472 }
473
474 int rk616_hdmi_initial(void)
475 {
476         int rc = HDMI_ERROR_SUCESS;
477
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;
486         
487         rk616_hdmi_reset();
488
489         rk616_hdmi_init_pol_set(g_rk616_hdmi,0);
490         if(hdmi->hdcp_power_on_cb)
491                 rc = hdmi->hdcp_power_on_cb();
492
493         return rc;
494 }