88d0a86abfebdf9ee2de3aef1f11326239c0626f
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / chips / rk3288 / rk3288_hdmi_hw.c
1 #include <linux/delay.h>
2 #include <linux/interrupt.h>
3 #include "rk3288_hdmi_hw.h"
4
5
6 static const struct phy_mpll_config_tab PHY_MPLL_TABLE[] = {    //opmode: 0:HDMI1.4     1:HDMI2.0
7 //      |pixclock|pixrepet|colordepth|prepdiv|tmdsmhl|opmode|fbdiv2|fbdiv1|ref_cntrl|nctrl|propctrl|intctrl|gmpctrl|
8         {27000000,      0,      8,      0,      0,      0,      2,      3,      0,      3,      3,      0,      0},
9         {74250000,      0,      8,      0,      0,      0,      1,      3,      0,      2,      5,      0,      1},
10         {148500000,     0,      8,      0,      0,      0,      1,      1,      0,      1,      7,      0,      2},
11         {297000000,     0,      8,      0,      0,      0,      1,      0,      0,      0,      7,      0,      3},
12         {297000000,     0,      16,     3,      3,      1,      1,      1,      0,      0,      5,      0,      3},
13         {594000000,     0,      8,      0,      3,      1,      1,      0,      0,      0,      3,      0,      3},
14 };
15
16 const struct phy_mpll_config_tab* get_phy_mpll_tab(int pixClock, char pixRepet, char colorDepth)
17 {
18         int i;
19
20         if(pixClock == 0)
21                 return NULL;
22
23         for(i = 0; i < ARRAY_SIZE(PHY_MPLL_TABLE); i++)
24         {
25                 if((PHY_MPLL_TABLE[i].pix_clock == pixClock) && (PHY_MPLL_TABLE[i].pix_repet == pixRepet)
26                         && (PHY_MPLL_TABLE[i].color_depth == colorDepth))
27                         return &PHY_MPLL_TABLE[i];
28         }
29         return NULL;
30 }
31
32 static void rk3288_hdmi_av_mute(struct hdmi *hdmi_drv, int enable)
33 {
34         int value = 0;
35         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
36
37         hdmi_msk_reg(hdmi_dev, FC_GCP, m_FC_SET_AVMUTE, v_FC_SET_AVMUTE(enable));
38
39         /* audio mute priority: AVMUTE, sample flat, validity */
40         /* AVMUTE also mutes video */
41         value = enable ? 0xF : 0;
42         hdmi_msk_reg(hdmi_dev, FC_AUDSCONF, m_AUD_PACK_SAMPFIT, v_AUD_PACK_SAMPFIT(value));
43
44 }
45
46 static void rk3288_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
47 {
48         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
49         if(hdmi_drv->pwr_mode == mode)
50                 return;
51
52         hdmi_dbg(hdmi->dev,"%s change pwr_mode %d --> %d\n",__FUNCTION__, hdmi_drv->pwr_mode, mode);
53         switch(mode)
54         {
55                 case NORMAL:
56                         hdmi_msk_reg(hdmi_dev, MC_SWRSTZREQ, m_TMDS_SWRST | m_PIXEL_SWRST,
57                                 v_TMDS_SWRST(0) | v_PIXEL_SWRST(0));
58                         hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE | m_PREPCLK_DISABLE | m_TMDSCLK_DISABLE | m_PIXELCLK_DISABLE,
59                                 v_AUDCLK_DISABLE(0) | v_PREPCLK_DISABLE(0) | v_TMDSCLK_DISABLE(0) | v_PIXELCLK_DISABLE(0));
60                         hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_TXPWRON_SIG, v_TXPWRON_SIG(1));
61                         rk3288_hdmi_av_mute(hdmi_drv, 1);
62                         break;
63                 case LOWER_PWR:
64                         hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE | m_PREPCLK_DISABLE | m_TMDSCLK_DISABLE | m_PIXELCLK_DISABLE,
65                                 v_AUDCLK_DISABLE(1) | v_PREPCLK_DISABLE(1) | v_TMDSCLK_DISABLE(1) | v_PIXELCLK_DISABLE(1));
66                         hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_TXPWRON_SIG, v_TXPWRON_SIG(0));
67                         break;
68                 default:
69                         hdmi_dbg(hdmi_drv->dev,"unkown hdmi pwr mode %d\n",mode);
70         }
71         hdmi_drv->pwr_mode = mode;
72 }
73
74 //i2c master reset
75 void rk3288_hdmi_i2cm_reset(struct rk3288_hdmi_device *hdmi_dev)
76 {
77         hdmi_msk_reg(hdmi_dev, I2CM_SOFTRSTZ, m_I2CM_SOFTRST, v_I2CM_SOFTRST(0));
78         msleep(5);
79 }
80
81 int rk3288_hdmi_detect_hotplug(struct hdmi *hdmi_drv)
82 {
83         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
84         u32 value = hdmi_readl(hdmi_dev,PHY_STAT0);
85
86         hdmi_dbg(hdmi_drv->dev, "[%s] reg%x value %02x\n", __FUNCTION__, PHY_STAT0, value);
87
88         if(value & m_PHY_HPD)
89                 return HDMI_HPD_ACTIVED;
90         else
91                 return HDMI_HPD_REMOVED;
92 }
93
94 int rk3288_hdmi_read_edid(struct hdmi *hdmi_drv, int block, unsigned char *buff)
95 {
96         int i = 0, n = 0, index = 0, interrupt = 0, ret = -1, trytime = 2;
97         int offset = (block%2)*0x80;
98         unsigned long flags;
99         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
100
101         hdmi_dbg(hdmi_drv->dev, "[%s] block %d\n", __FUNCTION__, block);
102         spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
103         hdmi_dev->i2cm_int = 0;
104         spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
105
106         //Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
107         hdmi_writel(hdmi_dev, I2CM_SS_SCL_HCNT_0_ADDR, 0x7a);
108         hdmi_writel(hdmi_dev, I2CM_SS_SCL_LCNT_0_ADDR, 0x8d);
109         hdmi_msk_reg(hdmi_dev, I2CM_DIV, m_I2CM_FAST_STD_MODE, v_I2CM_FAST_STD_MODE(STANDARD_MODE));    //Set Standard Mode
110
111         //Enable I2C interrupt for reading edid
112         hdmi_writel(hdmi_dev, IH_MUTE_I2CM_STAT0, v_SCDC_READREQ_MUTE(0) | v_I2CM_DONE_MUTE(0) | v_I2CM_ERR_MUTE(0));
113         hdmi_msk_reg(hdmi_dev, I2CM_INT, m_I2CM_DONE_MASK, v_I2CM_DONE_MASK(0));
114         hdmi_msk_reg(hdmi_dev, I2CM_CTLINT, m_I2CM_NACK_MASK | m_I2CM_ARB_MASK, v_I2CM_NACK_MASK(0) | v_I2CM_ARB_MASK(0));
115
116         hdmi_writel(hdmi_dev, I2CM_SLAVE, DDC_I2C_EDID_ADDR);
117         hdmi_writel(hdmi_dev, I2CM_SEGADDR, DDC_I2C_SEG_ADDR);
118         while(trytime--) {
119                 for(n = 0; n < HDMI_EDID_BLOCK_SIZE/8; n++) {
120                         // Config EDID block and segment addr
121                         hdmi_writel(hdmi_dev, I2CM_SEGPTR, block/2);
122                         hdmi_writel(hdmi_dev, I2CM_ADDRESS, offset + 8*n);
123                         //enable extend sequential read operation
124                         hdmi_msk_reg(hdmi_dev, I2CM_OPERATION, m_I2CM_RD8_EXT, v_I2CM_RD8_EXT(1));
125
126                         i = 200;
127                         while(i--)
128                         {
129                                 spin_lock_irqsave(&hdmi_drv->irq_lock, flags);
130                                 interrupt = hdmi_dev->i2cm_int;
131                                 hdmi_dev->i2cm_int = 0;
132                                 spin_unlock_irqrestore(&hdmi_drv->irq_lock, flags);
133                                 if(interrupt & (m_SCDC_READREQ | m_I2CM_DONE | m_I2CM_ERROR))
134                                         break;
135                                 msleep(5);
136                         }
137
138                         if((i == 0) || (interrupt & m_I2CM_ERROR)) {
139                                 hdmi_err(hdmi_drv->dev, "[%s] edid read error\n", __FUNCTION__);
140                                 rk3288_hdmi_i2cm_reset(hdmi_dev);
141                                 break;
142                         }
143
144                         if(interrupt & m_I2CM_DONE) {
145                                 for(index = 0; index < 8; index++) {
146                                         buff[8*n + index] = hdmi_readl(hdmi_dev, I2CM_READ_BUFF0 + index);
147                                 }
148                                 continue;
149
150                                 if(n == HDMI_EDID_BLOCK_SIZE/8 - 1) {
151                                         ret = 0;
152                                         hdmi_dbg(hdmi_drv->dev, "[%s] edid read sucess\n", __FUNCTION__);
153
154                                 #ifdef HDMI_DEBUG
155                                         for(i = 0; i < 128; i++) {
156                                                 printk("%02x ,", buff[i]);
157                                                 if( (i + 1) % 16 == 0)
158                                                         printk("\n");
159                                         }
160                                 #endif
161                                         goto exit;
162                                 }
163                         }
164                 }
165
166                 hdmi_dbg(hdmi_drv->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
167                 msleep(100);
168         }
169
170 exit:
171         //Disable I2C interrupt
172         hdmi_msk_reg(hdmi_dev, IH_MUTE_I2CM_STAT0, m_I2CM_DONE_MUTE | m_I2CM_ERR_MUTE, v_I2CM_DONE_MUTE(1) | v_I2CM_ERR_MUTE(1));
173         hdmi_msk_reg(hdmi_dev, I2CM_INT, m_I2CM_DONE_MASK, v_I2CM_DONE_MASK(1));
174         hdmi_msk_reg(hdmi_dev, I2CM_CTLINT, m_I2CM_NACK_MASK | m_I2CM_ARB_MASK, v_I2CM_NACK_MASK(1) | v_I2CM_ARB_MASK(1));
175         return ret;
176 }
177
178 static int rk3288_hdmi_video_forceOutput(struct hdmi *hdmi_drv, char enable)
179 {
180         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
181
182         hdmi_msk_reg(hdmi_dev, FC_DBGFORCE, m_FC_FORCEAUDIO, v_FC_FORCEAUDIO(0));
183
184         if(enable) {    /*Force output Blue*/
185                 hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x00);       /*R*/
186                 hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x00);       /*G*/
187                 hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0xff);       /*B*/
188                 hdmi_msk_reg(hdmi_dev, FC_DBGFORCE, m_FC_FORCEVIDEO, v_FC_FORCEVIDEO(1));
189         }
190         else {
191                 hdmi_msk_reg(hdmi_dev, FC_DBGFORCE, m_FC_FORCEVIDEO, v_FC_FORCEVIDEO(0));
192                 hdmi_writel(hdmi_dev, FC_DBGTMDS2, 0x00);       /*R*/
193                 hdmi_writel(hdmi_dev, FC_DBGTMDS1, 0x00);       /*G*/
194                 hdmi_writel(hdmi_dev, FC_DBGTMDS0, 0x00);       /*B*/
195         }
196
197         return 0;
198 }
199
200 static int rk3288_hdmi_video_frameComposer(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)        //TODO Daisen wait to add support 3D
201 {
202         int i = 0, value = 0;
203         int h_act = 0, v_act = 0;
204         int h_syncdelay = 0, v_syncdelay = 0;
205         int h_sync = 0, v_sync = 0;
206         int h_blank = 0, v_blank = 0;
207         int vsync_pol = hdmi_drv->lcdc->cur_screen->pin_vsync;
208         int hsync_pol = hdmi_drv->lcdc->cur_screen->pin_hsync;
209         int de_pol = hdmi_drv->lcdc->cur_screen->pin_den;
210         struct fb_videomode *mode = NULL;
211         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
212
213         mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
214         if(mode == NULL) {
215                 hdmi_err(hdmi_drv->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
216                 return -ENOENT;
217         }
218
219         hdmi_drv->tmdsclk = mode->pixclock;
220         if(hdmi_drv->tmdsclk > 340000000) {     //used for HDMI 2.0 TX  //TODO Daisen wait to modify HDCP KEEPOUT
221                 hdmi_msk_reg(hdmi_dev, FC_INVIDCONF, m_FC_HDCP_KEEPOUT, v_FC_HDCP_KEEPOUT(1));
222                 hdmi_msk_reg(hdmi_dev, FC_SCRAMBLER_CTRL, m_FC_SCRAMBLE_EN, v_FC_SCRAMBLE_EN(1));
223         }
224
225         hdmi_msk_reg(hdmi_dev, FC_INVIDCONF, m_FC_VSYNC_POL | m_FC_HSYNC_POL | m_FC_DE_POL | m_FC_HDMI_DVI | m_FC_INTERLACE_MODE,
226                 v_FC_VSYNC_POL(vsync_pol) | v_FC_HSYNC_POL(hsync_pol) | v_FC_DE_POL(de_pol) | v_FC_HDMI_DVI(vpara->output_mode) | v_FC_INTERLACE_MODE(mode->vmode));
227         hdmi_msk_reg(hdmi_dev, FC_INVIDCONF, m_FC_VBLANK, v_FC_VBLANK(mode->vmode));
228
229         h_act = mode->xres;
230         hdmi_writel(hdmi_dev, FC_INHACTIV1, v_FC_HACTIVE1(h_act >> 8));
231         hdmi_writel(hdmi_dev, FC_INHACTIV0, (h_act & 0xff));
232
233         v_act = mode->yres;
234         hdmi_writel(hdmi_dev, FC_INVACTIV1, v_FC_VACTIVE1(v_act >> 8));
235         hdmi_writel(hdmi_dev, FC_INVACTIV0, (v_act & 0xff));
236
237         h_blank = mode->hsync_len + mode->left_margin + mode->right_margin;
238         hdmi_writel(hdmi_dev, FC_INHBLANK1, v_FC_HBLANK1(h_blank >> 8));
239         hdmi_writel(hdmi_dev, FC_INHBLANK0, (h_blank & 0xff));
240
241         v_blank = mode->vsync_len + mode->upper_margin + mode->lower_margin;
242         hdmi_writel(hdmi_dev, FC_INVBLANK, (v_blank & 0xff));
243
244         h_syncdelay = mode->right_margin;
245         hdmi_writel(hdmi_dev, FC_HSYNCINDELAY1, v_FC_HSYNCINDEAY1(h_syncdelay >> 8));
246         hdmi_writel(hdmi_dev, FC_HSYNCINDELAY0, (h_syncdelay & 0xff));
247
248         v_syncdelay = mode->lower_margin;
249         hdmi_writel(hdmi_dev, FC_VSYNCINDELAY, (v_syncdelay & 0xff));
250
251         h_sync = mode->hsync_len;
252         hdmi_writel(hdmi_dev, FC_HSYNCINWIDTH1, v_FC_HSYNCWIDTH1(h_sync >> 8));
253         hdmi_writel(hdmi_dev, FC_HSYNCINWIDTH0, (h_sync & 0xff));
254
255         v_sync = mode->vsync_len;
256         hdmi_writel(hdmi_dev, FC_VSYNCINWIDTH, (v_sync & 0xff));
257
258         /*Set the control period minimum duration(min. of 12 pixel clock cycles, refer to HDMI 1.4b specification)*/
259         hdmi_writel(hdmi_dev, FC_CTRLDUR, 12);
260         hdmi_writel(hdmi_dev, FC_EXCTRLDUR, 32);
261
262         /* spacing < 256^2 * config / tmdsClock, spacing <= 50ms
263          * worst case: tmdsClock == 25MHz => config <= 19
264          */
265         hdmi_writel(hdmi_dev, FC_EXCTRLSPAC, 1);
266
267         /*Set PreambleFilter*/
268         for (i = 0; i < 3; i++) {
269                 value = (i + 1) * 11;
270                 if (i == 0)             /*channel 0*/
271                         hdmi_writel(hdmi_dev, FC_CH0PREAM, value);
272                 else if (i == 1)        /*channel 1*/
273                         hdmi_writel(hdmi_dev, FC_CH1PREAM, value & 0x3f);
274                 else if (i == 2)        /*channel 2*/
275                         hdmi_writel(hdmi_dev, FC_CH2PREAM, value & 0x3f);
276         }
277
278         /*Set PixelRepetition:No pixel repetition*/
279         hdmi_writel(hdmi_dev, FC_PRCONF, v_FC_PR_FACTOR(1));
280
281         return 0;
282 }
283
284 static int rk3288_hdmi_video_packetizer(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
285 {
286         int color_depth = 0, output_select = 0;
287         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
288
289         if(vpara->output_color == VIDEO_OUTPUT_RGB444 || vpara->output_color == VIDEO_OUTPUT_YCBCR444
290                 || vpara->output_color == VIDEO_OUTPUT_YCBCR420) {
291                 output_select = OUT_FROM_8BIT_BYPASS;
292                 color_depth = COLOR_DEPTH_24BIT;        //TODO modify if need
293         }
294         else if(vpara->output_color == VIDEO_OUTPUT_YCBCR420) {
295                 hdmi_msk_reg(hdmi_dev, VP_REMAP, m_YCC422_SIZE, v_YCC422_SIZE(0));      //TODO modify accord to the color depth if need
296                 output_select = OUT_FROM_YCC422_REMAP;
297         }
298         else {
299                 hdmi_err(hdmi_drv->dev, "invalid output color type: %d", vpara->output_color);
300                 return -1;
301         }
302
303         /*no pixel repet*/
304         hdmi_writel(hdmi_dev, VP_PR_CD, v_COLOR_DEPTH(color_depth) | v_DESIRED_PR_FACTOR(0));
305         hdmi_msk_reg(hdmi_dev, VP_STUFF, m_PR_STUFFING, v_PR_STUFFING(1));
306         hdmi_msk_reg(hdmi_dev, VP_CONF, m_PIXEL_REPET_EN | m_BYPASS_SEL, v_PIXEL_REPET_EN(0) | v_BYPASS_SEL(1));
307
308         /*video output select*/
309         if(output_select == OUT_FROM_PIXEL_PACKING) { /* pixel packing */
310                 hdmi_msk_reg(hdmi_dev, VP_CONF, m_BYPASS_EN | m_PIXEL_PACK_EN | m_YCC422_EN | m_OUTPUT_SEL,
311                         v_BYPASS_EN(0) | v_PIXEL_PACK_EN(1) | v_YCC422_EN(0) | v_OUTPUT_SEL(output_select));
312         }
313         else if(output_select == OUT_FROM_YCC422_REMAP) { /* YCC422 */
314                 hdmi_msk_reg(hdmi_dev, VP_CONF, m_BYPASS_EN | m_PIXEL_PACK_EN | m_YCC422_EN | m_OUTPUT_SEL,
315                         v_BYPASS_EN(0) | v_PIXEL_PACK_EN(0) | v_YCC422_EN(1) | v_OUTPUT_SEL(output_select));
316         }
317         else if (output_select == OUT_FROM_8BIT_BYPASS || output_select == 3) { /* bypass */
318                 hdmi_msk_reg(hdmi_dev, VP_CONF, m_BYPASS_EN | m_PIXEL_PACK_EN | m_YCC422_EN | m_OUTPUT_SEL,
319                         v_BYPASS_EN(1) | v_PIXEL_PACK_EN(0) | v_YCC422_EN(0) | v_OUTPUT_SEL(output_select));
320         }
321
322         /* YCC422 and pixel packing stuffing*/
323         hdmi_msk_reg(hdmi_dev, VP_STUFF, m_YCC422_STUFFING | m_PP_STUFFING, v_YCC422_STUFFING(1) | v_PP_STUFFING(1));
324
325         return 0;
326 }
327
328 int rk3288_hdmi_video_sampler(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
329 {
330         int map_code = 0;
331         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
332
333         if(vpara->input_color == VIDEO_INPUT_COLOR_RGB || vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444
334                 || vpara->input_color == VIDEO_INPUT_COLOR_YCBCR420) {
335                 map_code = VIDEO_RGB444_8BIT;   //TODO modify accord to color depth
336                 map_code += (vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444) ? 8 : 0;
337         }
338         else if(vpara->input_color == VIDEO_INPUT_COLOR_YCBCR422) {
339                 /* YCC422 mapping is discontinued - only map 1 is supported */
340                 map_code = VIDEO_YCBCR422_8BIT;
341         }
342         else {
343                 hdmi_err(hdmi_drv->dev, "invalid input color type: %d", vpara->input_color);
344                 return -1;
345         }
346
347         //Set Data enable signal from external and set video sample input mapping
348         hdmi_msk_reg(hdmi_dev, TX_INVID0, m_INTERNAL_DE_GEN | m_VIDEO_MAPPING, v_INTERNAL_DE_GEN(0) | v_VIDEO_MAPPING(map_code));
349
350         //TODO Daisen
351         hdmi_writel(hdmi_dev, TX_GYDATA0, 0x00);
352         hdmi_writel(hdmi_dev, TX_GYDATA1, 0x00);
353         hdmi_msk_reg(hdmi_dev, TX_INSTUFFING, m_GYDATA_STUFF, v_GYDATA_STUFF(1));
354         hdmi_writel(hdmi_dev, TX_RCRDATA0, 0x00);
355         hdmi_writel(hdmi_dev, TX_RCRDATA1, 0x00);
356         hdmi_msk_reg(hdmi_dev, TX_INSTUFFING, m_RCRDATA_STUFF, v_RCRDATA_STUFF(1));
357         hdmi_writel(hdmi_dev, TX_BCBDATA0, 0x00);
358         hdmi_writel(hdmi_dev, TX_BCBDATA1, 0x00);
359         hdmi_msk_reg(hdmi_dev, TX_INSTUFFING, m_BCBDATA_STUFF, v_BCBDATA_STUFF(1));
360         return 0;
361 }
362
363 static int rk3288_hdmi_read_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_addr, int *val)
364 {
365         int trytime = 2, i = 0, op_status = 0;
366
367         mutex_lock(&hdmi_dev->int_mutex);
368         hdmi_dev->phy_i2cm_int = 0;
369         mutex_unlock(&hdmi_dev->int_mutex);
370
371         while(trytime--) {
372                 hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
373                 hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_READ);
374
375                 i = 100;
376                 while(i--) {
377                         mutex_lock(&hdmi_dev->int_mutex);
378                         //op_status = hdmi_readl(hdmi_dev, PHY_I2CM_INT);
379                         op_status = hdmi_dev->phy_i2cm_int;
380                         hdmi_dev->phy_i2cm_int = 0;
381                         mutex_unlock(&hdmi_dev->int_mutex);
382                         if(op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
383                                 break;
384                         }
385                         msleep(10);
386                 }
387
388                 if(op_status & m_I2CMPHY_DONE) {
389                         *val = (hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_1) >> 8) & 0xff;
390                         *val += (hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_0) & 0xff);
391                         return 0;
392                 }
393                 else {
394                         hdmi_err(hdmi_dev->dev, "[%s] operation error,trytime=%d\n", __FUNCTION__,trytime);
395                 }
396                 msleep(100);
397         }
398
399         return -1;
400 }
401
402 static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_addr, int val)
403 {
404         int trytime = 2, i = 0, op_status = 0;
405
406         mutex_lock(&hdmi_dev->int_mutex);
407         hdmi_dev->phy_i2cm_int = 0;
408         mutex_unlock(&hdmi_dev->int_mutex);
409
410         while(trytime--) {
411                 hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
412                 hdmi_writel(hdmi_dev, PHY_I2CM_DATAO_1, (val >> 8) & 0xff);
413                 hdmi_writel(hdmi_dev, PHY_I2CM_DATAO_0, val & 0xff);
414                 hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_WRITE);
415
416                 i = 100;
417                 while(i--) {
418                         mutex_lock(&hdmi_dev->int_mutex);
419                         //op_status = hdmi_readl(hdmi_dev, PHY_I2CM_INT);
420                         op_status = hdmi_dev->phy_i2cm_int;
421                         hdmi_dev->phy_i2cm_int = 0;
422                         mutex_unlock(&hdmi_dev->int_mutex);
423                         if(op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
424                                 break;
425                         }
426                         msleep(10);
427                 }
428
429                 if(op_status & m_I2CMPHY_DONE) {
430                         return 0;
431                 }
432                 else {
433                         hdmi_err(hdmi_dev->dev, "[%s] operation error,trytime=%d\n", __FUNCTION__,trytime);
434                 }
435                 msleep(100);
436         }
437
438         return -1;
439 }
440
441 static int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv)
442 {
443         int stat = 0, i = 0;
444         //char color_depth = COLOR_DEPTH_24BIT;//COLOR_DEPTH_24BIT_DEFAULT;
445         char pix_repet = NO_PIXEL_REPET;
446         const struct phy_mpll_config_tab *phy_mpll = NULL;
447         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
448
449         //get phy_type,if PHY_GEN2==1 config phy register
450         //phy_type = hdmi_readl(hdmi_dev, CONFIG2_ID);
451         //if(phy_type != HDMI_3D_TX_WITH_HEAC_PHY && phy_type != HDMI_3D_TX_PHY) {
452         //      printk("%s: PHY_GEN2 = 0,No need to config phy", __FUNCTION__);
453         //      return;
454         //}
455
456         //hdmi_writel(hdmi_dev, PHY_CONF0, 0x32);
457         hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG, v_PDDQ_SIG(1) | v_TXPWRON_SIG(0));
458         hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
459         //the resolution that we used is no pixel repet,refer to the CEA-861 specification.
460         //hdmi_writel(hdmi_dev, VP_PR_CD, v_COLOR_DEPTH(color_depth) | v_DESIRED_PR_FACTOR(pix_repet));
461         //msleep(5);
462         hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
463
464         //Set slave address as PHY GEN2 address
465         hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_I2C_SLAVE_ADDR);      //TODO Daisen wait to modify
466
467         rk3288_hdmi_write_phy(hdmi_dev, 0x13, 0x0000); /* PLLPHBYCTRL */
468         rk3288_hdmi_write_phy(hdmi_dev, 0x17, 0x0006);
469         /* RESISTANCE TERM 133Ohm Cfg  */
470         rk3288_hdmi_write_phy(hdmi_dev, 0x19, 0x0005); /* TXTERM */     //TODO Daisen wait to modify
471         /* REMOVE CLK TERM */
472         rk3288_hdmi_write_phy(hdmi_dev, 0x05, 0x8000); /* CKCALCTRL */
473
474         //config the required PHY I2C register
475         phy_mpll = get_phy_mpll_tab(hdmi_drv->tmdsclk, pix_repet, 8);
476         if(phy_mpll) {
477                 rk3288_hdmi_write_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG, v_PREP_DIV(phy_mpll->prep_div) | v_TMDS_CNTRL(phy_mpll->tmdsmhl_cntrl) | v_OPMODE(phy_mpll->opmode) |
478                         v_FBDIV2_CNTRL(phy_mpll->fbdiv2_cntrl) | v_FBDIV1_CNTRL(phy_mpll->fbdiv1_cntrl) | v_REF_CNTRL(phy_mpll->ref_cntrl) | v_MPLL_N_CNTRL(phy_mpll->n_cntrl));
479                 rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLCURRCTRL, v_MPLL_PROP_CNTRL(phy_mpll->prop_cntrl) | v_MPLL_INT_CNTRL(phy_mpll->int_cntrl));
480                 rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLGMPCTRL, v_MPLL_GMP_CNTRL(phy_mpll->gmp_cntrl));
481         }
482
483         //power on PHY
484         //hdmi_writel(hdmi_dev, PHY_CONF0, 0x2a);
485         hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
486                 v_PDDQ_SIG(0) | v_TXPWRON_SIG(1) | v_ENHPD_RXSENSE_SIG(1));
487
488         //check if the PHY PLL is locked
489         #define PHY_TIMEOUT     10000
490         while(i++ < PHY_TIMEOUT) {
491                 if ((i % 100) == 0) {
492                         stat = hdmi_readl(hdmi_dev, PHY_STAT0);
493                         if(stat & m_PHY_LOCK) {
494                                 //hdmi_writel(hdmi_dev, PHY_STAT0, v_PHY_LOCK(1));
495                                 break;
496                         }
497                 }
498         }
499         if((stat & m_PHY_LOCK) == 0) {
500                 hdmi_err(hdmi_dev->dev, "PHY PLL not locked\n");
501                 return -1;
502         }
503
504         return 0;
505 }
506
507 static void rk3288_hdmi_config_avi(struct hdmi *hdmi_drv, unsigned char vic, unsigned char output_color)
508 {
509         int clolorimetry, aspect_ratio, y1y0;
510         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
511
512         //Set AVI infoFrame Data byte1
513         if(output_color == VIDEO_OUTPUT_YCBCR444)
514                 y1y0 = AVI_COLOR_MODE_YCBCR444;
515         else if(output_color == VIDEO_OUTPUT_YCBCR422)
516                 y1y0 = AVI_COLOR_MODE_YCBCR422;
517         else if(output_color == VIDEO_OUTPUT_YCBCR420)
518                 y1y0 = AVI_COLOR_MODE_YCBCR420;
519         else
520                 y1y0 = AVI_COLOR_MODE_RGB;
521
522         hdmi_msk_reg(hdmi_dev, FC_AVICONF0, m_FC_ACTIV_FORMAT | m_FC_RGC_YCC, v_FC_RGC_YCC(y1y0) | v_FC_ACTIV_FORMAT(1));
523
524         //Set AVI infoFrame Data byte2
525         switch(vic)
526         {
527                 case HDMI_720x480i_60Hz_4_3:
528                 case HDMI_720x576i_50Hz_4_3:
529                 case HDMI_720x480p_60Hz_4_3:
530                 case HDMI_720x576p_50Hz_4_3:
531                         aspect_ratio = AVI_CODED_FRAME_ASPECT_4_3;
532                         clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
533                         break;
534                 case HDMI_720x480i_60Hz_16_9:
535                 case HDMI_720x576i_50Hz_16_9:
536                 case HDMI_720x480p_60Hz_16_9:
537                 case HDMI_720x576p_50Hz_16_9:
538                         aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
539                         clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
540                         break;
541                 default:
542                         aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
543                         clolorimetry = AVI_COLORIMETRY_ITU709;
544         }
545
546         if(output_color == VIDEO_OUTPUT_RGB444)
547                 clolorimetry = AVI_COLORIMETRY_NO_DATA;
548
549         hdmi_writel(hdmi_dev, FC_AVICONF1, v_FC_COLORIMETRY(clolorimetry) | v_FC_PIC_ASPEC_RATIO(aspect_ratio) | v_FC_ACT_ASPEC_RATIO(ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME));
550
551         //Set AVI infoFrame Data byte3
552         hdmi_writel(hdmi_dev, FC_AVICONF2, 0x00);
553
554         //Set AVI infoFrame Data byte4
555         hdmi_writel(hdmi_dev, FC_AVIVID, (vic & 0xff));
556
557         //Set AVI infoFrame Data byte5
558         hdmi_msk_reg(hdmi_dev, FC_AVICONF3, m_FC_YQ | m_FC_CN, v_FC_YQ(YQ_LIMITED_RANGE) | v_FC_CN(CN_GRAPHICS));
559
560 }
561
562
563 static const char coeff_csc[][24] = {
564                 //   G          R           B           Bias
565                 //   A1    |    A2     |    A3     |    A4    |
566                 //   B1    |    B2     |    B3     |    B4    |
567                 //   C1    |    C2     |    C3     |    C4    |
568         {       //CSC_RGB_TO_ITU601
569                 0x25, 0x91, 0x13, 0x22, 0x07, 0x4b, 0x00, 0x00,         //Y
570                 0x65, 0x35, 0x20, 0x00, 0x7a, 0xcc, 0x02, 0x00,         //Cr
571                 0x6a, 0xcd, 0x75, 0x34, 0x20, 0x00, 0x02, 0x00,         //Cb
572         },
573         {       //CSC_RGB_TO_ITU709
574                 0x2d, 0xc5, 0x0d, 0x9b, 0x04, 0x9e, 0x00, 0x00,         //Y
575                 0x62, 0xf0, 0x20, 0x00, 0x7d, 0x11, 0x02, 0x00,         //Cr
576                 0x67, 0x56, 0x78, 0xab, 0x20, 0x00, 0x02, 0x00,         //Cb
577         },
578                 //Y             Cr          Cb          Bias
579         {       //CSC_ITU601_TO_RGB
580                 0x20, 0x00, 0x69, 0x26, 0x74, 0xfd, 0x01, 0x0e,         //R 
581                 0x20, 0x00, 0x2c, 0xdd, 0x00, 0x00, 0x7e, 0x9a,         //G
582                 0x20, 0x00, 0x00, 0x00, 0x38, 0xb4, 0x7e, 0x3b,         //B
583         },
584         {       //CSC_ITU709_TO_RGB
585                 0x20, 0x00, 0x71, 0x06, 0x7a, 0x02, 0x00, 0xa7,         //R
586                 0x20, 0x00, 0x32, 0x64, 0x00, 0x00, 0x7e, 0x6d,         //G
587                 0x20, 0x00, 0x00, 0x00, 0x3b, 0x61, 0x7e, 0x25,         //B
588         },
589
590 };
591
592 static int rk3288_hdmi_video_csc(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
593 {
594         int i, mode, interpolation, decimation, csc_scale;
595         const char *coeff = NULL;
596         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
597
598         if( ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)) ||
599                 ((vpara->input_color != VIDEO_INPUT_COLOR_RGB) && (vpara->output_color != VIDEO_OUTPUT_RGB444) ))
600         {
601                 hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(0));
602                 return 0;
603         }
604
605         if(vpara->input_color == VIDEO_INPUT_COLOR_YCBCR422 &&
606                 (vpara->output_color == VIDEO_OUTPUT_RGB444 || vpara->output_color == VIDEO_OUTPUT_YCBCR444)) {
607                 interpolation = 1;
608                 hdmi_msk_reg(hdmi_dev, CSC_CFG, m_CSC_INTPMODE, v_CSC_INTPMODE(interpolation));
609         }
610
611         if((vpara->input_color == VIDEO_INPUT_COLOR_RGB || vpara->input_color == VIDEO_INPUT_COLOR_YCBCR444)
612                 && vpara->output_color == VIDEO_OUTPUT_YCBCR422) {
613                 decimation = 1;
614                 hdmi_msk_reg(hdmi_dev, CSC_CFG, m_CSC_DECIMODE, v_CSC_DECIMODE(decimation));
615         }
616
617         switch(vpara->vic)
618         {
619                 case HDMI_720x480i_60Hz_4_3:
620                 case HDMI_720x576i_50Hz_4_3:
621                 case HDMI_720x480p_60Hz_4_3:
622                 case HDMI_720x576p_50Hz_4_3:
623                 case HDMI_720x480i_60Hz_16_9:
624                 case HDMI_720x576i_50Hz_16_9:
625                 case HDMI_720x480p_60Hz_16_9:
626                 case HDMI_720x576p_50Hz_16_9:
627                         if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
628                                 mode = CSC_RGB_TO_ITU601;
629                                 csc_scale = 0;
630                         }
631                         else if(vpara->output_color == VIDEO_OUTPUT_RGB444) {
632                                 mode = CSC_ITU601_TO_RGB;
633                                 csc_scale = 1;
634                         }
635                         break;
636                 default:
637                         if(vpara->input_color == VIDEO_INPUT_COLOR_RGB) {
638                                 mode = CSC_RGB_TO_ITU709;
639                                 csc_scale = 0;
640                         }
641                         else if(vpara->output_color == VIDEO_OUTPUT_RGB444) {
642                                 mode = CSC_ITU709_TO_RGB;
643                                 csc_scale = 1;
644                         }
645                         break;
646         }
647
648         coeff = coeff_csc[mode];
649         for(i = 0; i < 24; i++) {
650                 hdmi_writel(hdmi_dev, CSC_COEF_A1_MSB + i, coeff[i]);
651         }
652         hdmi_msk_reg(hdmi_dev, CSC_SCALE, m_CSC_SCALE, v_CSC_SCALE(csc_scale));
653         //CSC_COLOR_DEPTH is not set and retain default:24 bits per pixel video,TODO modify if need
654
655         //enable CSC
656         hdmi_msk_reg(hdmi_dev, MC_FLOWCTRL, m_FEED_THROUGH_OFF, v_FEED_THROUGH_OFF(1));
657         return 0;
658 }
659
660
661 int rk3288_hdmi_config_video(struct hdmi *hdmi_drv, struct hdmi_video_para *vpara)
662 {
663         if(hdmi_drv->pwr_mode == LOWER_PWR)
664                 rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
665
666         //Color space convert
667         if (rk3288_hdmi_video_forceOutput(hdmi_drv, 1) < 0)
668                 return -1;
669         if (rk3288_hdmi_video_frameComposer(hdmi_drv, vpara) < 0)
670                 return -1;
671         if (rk3288_hdmi_video_packetizer(hdmi_drv, vpara) < 0)
672                 return -1;
673         if (rk3288_hdmi_video_csc(hdmi_drv, vpara) < 0)
674                 return -1;
675         if (rk3288_hdmi_video_sampler(hdmi_drv, vpara) < 0)
676                 return -1;
677
678         if(vpara->output_mode == OUTPUT_HDMI) {
679                 rk3288_hdmi_config_avi(hdmi_drv, vpara->vic, vpara->output_color);
680                 hdmi_dbg(hdmi_drv->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
681         }
682         else {
683                 hdmi_dbg(hdmi_drv->dev, "[%s] sucess output DVI.\n", __FUNCTION__);
684         }
685
686         rk3288_hdmi_config_phy(hdmi_drv);
687         rk3288_hdmi_control_output(hdmi_drv, 0);
688         return 0;
689 }
690
691 static void rk3288_hdmi_config_aai(struct hdmi *hdmi_drv, struct hdmi_audio *audio)
692 {
693         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
694
695         //Refer to CEA861-E Audio infoFrame
696         //Set both Audio Channel Count and Audio Coding Type Refer to Stream Head for HDMI
697         hdmi_msk_reg(hdmi_dev, FC_AUDICONF0, m_FC_CHN_CNT | m_FC_CODING_TYEP, v_FC_CHN_CNT(0) | v_FC_CODING_TYEP(0));
698
699         //Set both Audio Sample Size and Sample Frequency Refer to Stream Head for HDMI
700         hdmi_msk_reg(hdmi_dev, FC_AUDICONF1, m_FC_SAMPLE_SIZE | m_FC_SAMPLE_FREQ, v_FC_SAMPLE_SIZE(0) | v_FC_SAMPLE_FREQ(0));
701
702         //Set Channel Allocation
703         hdmi_writel(hdmi_dev, FC_AUDICONF2, 0x00);
704
705         //Set LFEPBL¡¢DOWN-MIX INH and LSV
706         hdmi_writel(hdmi_dev, FC_AUDICONF3, 0x00);
707 }
708
709 int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio)
710 {
711         int word_length = 0, channel = 0, N = 0, mclk_fs;
712         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
713
714         if(audio->channel < 3)
715                 channel = I2S_CHANNEL_1_2;
716         else if(audio->channel < 5)
717                 channel = I2S_CHANNEL_3_4;
718         else if(audio->channel < 7)
719                 channel = I2S_CHANNEL_5_6;
720         else
721                 channel = I2S_CHANNEL_7_8;
722
723         switch(audio->rate)
724         {
725                 case HDMI_AUDIO_FS_32000:
726                         mclk_fs = FS_128;
727                         if(hdmi_drv->tmdsclk >= 594000000)
728                                 N = N_32K_HIGHCLK;
729                         else if(hdmi_drv->tmdsclk == 297000000)
730                                 N = N_32K_MIDCLK;
731                         else
732                                 N = N_32K_LOWCLK;
733                         break;
734                 case HDMI_AUDIO_FS_44100:
735                         mclk_fs = FS_128;
736                         if(hdmi_drv->tmdsclk >= 594000000)
737                                 N = N_441K_HIGHCLK;
738                         else if(hdmi_drv->tmdsclk == 297000000)
739                                 N = N_441K_MIDCLK;
740                         else
741                                 N = N_441K_LOWCLK;
742                         break;
743                 case HDMI_AUDIO_FS_48000:
744                         mclk_fs = FS_128;
745                         if(hdmi_drv->tmdsclk >= 594000000)      //FS_153.6
746                                 N = N_48K_HIGHCLK;
747                         else if(hdmi_drv->tmdsclk == 297000000)
748                                 N = N_48K_MIDCLK;
749                         else
750                                 N = N_48K_LOWCLK;
751                         break;
752                 case HDMI_AUDIO_FS_88200:
753                         mclk_fs = FS_128;
754                         if(hdmi_drv->tmdsclk >= 594000000)
755                                 N = N_882K_HIGHCLK;
756                         else if(hdmi_drv->tmdsclk == 297000000)
757                                 N = N_882K_MIDCLK;
758                         else
759                                 N = N_882K_LOWCLK;
760                         break;
761                 case HDMI_AUDIO_FS_96000:
762                         mclk_fs = FS_128;
763                         if(hdmi_drv->tmdsclk >= 594000000)      //FS_153.6
764                                 N = N_96K_HIGHCLK;
765                         else if(hdmi_drv->tmdsclk == 297000000)
766                                 N = N_96K_MIDCLK;
767                         else
768                                 N = N_96K_LOWCLK;
769                         break;
770                 case HDMI_AUDIO_FS_176400:
771                         mclk_fs = FS_128;
772                         if(hdmi_drv->tmdsclk >= 594000000)
773                                 N = N_1764K_HIGHCLK;
774                         else if(hdmi_drv->tmdsclk == 297000000)
775                                 N = N_1764K_MIDCLK;
776                         else
777                                 N = N_1764K_LOWCLK;
778                         break;
779                 case HDMI_AUDIO_FS_192000:
780                         mclk_fs = FS_128;
781                         if(hdmi_drv->tmdsclk >= 594000000)      //FS_153.6
782                                 N = N_192K_HIGHCLK;
783                         else if(hdmi_drv->tmdsclk == 297000000)
784                                 N = N_192K_MIDCLK;
785                         else
786                                 N = N_192K_LOWCLK;
787                         break;
788                 default:
789                         hdmi_err(hdmi_drv->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
790                         return -ENOENT;
791         }
792
793         switch(audio->word_length)
794         {
795                 case HDMI_AUDIO_WORD_LENGTH_16bit:
796                         word_length = I2S_16BIT_SAMPLE;
797                         break;
798                 case HDMI_AUDIO_WORD_LENGTH_20bit:
799                         word_length = I2S_20BIT_SAMPLE;
800                         break;
801                 case HDMI_AUDIO_WORD_LENGTH_24bit:
802                         word_length = I2S_24BIT_SAMPLE;
803                         break;
804                 default:
805                         word_length = I2S_16BIT_SAMPLE;
806         }
807
808         /* more than 2 channels => layout 1 else layout 0 */
809         //value = (audio->channel > 2) ? 1 : 0; //TODO Daisen wait to modify
810         //hdmi_msk_reg(hdmi_dev, FC_AUDSCONF, m_AUD_PACK_LAYOUT, v_AUD_PACK_LAYOUT(value));
811
812         if(hdmi_drv->audio.type == INPUT_SPDIF) {
813                 hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_I2S_SEL, v_I2S_SEL(AUDIO_SPDIF_GPA));
814                 hdmi_msk_reg(hdmi_dev, AUD_SPDIF1, m_SET_NLPCM | m_SPDIF_WIDTH, v_SET_NLPCM(PCM_LINEAR) | v_SPDIF_WIDTH(word_length));
815                 //Mask fifo empty and full int and reset fifo
816                 hdmi_msk_reg(hdmi_dev, AUD_SPDIFINT, m_FIFO_EMPTY_MASK | m_FIFO_FULL_MASK, v_FIFO_EMPTY_MASK(1) | v_FIFO_FULL_MASK(1));
817                 hdmi_msk_reg(hdmi_dev, AUD_SPDIF0, m_SW_SAUD_FIFO_RST, v_SW_SAUD_FIFO_RST(1));
818         }
819         else {
820                 hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_I2S_SEL | m_I2S_IN_EN, v_I2S_SEL(AUDIO_I2S) | v_I2S_IN_EN(0x0f));
821                 hdmi_writel(hdmi_dev, AUD_CONF1, v_I2S_MODE(I2S_STANDARD_MODE) | v_I2S_WIDTH(word_length));
822                 //Mask fifo empty and full int and reset fifo
823                 hdmi_msk_reg(hdmi_dev, AUD_INT, m_FIFO_EMPTY_MASK | m_FIFO_FULL_MASK, v_FIFO_EMPTY_MASK(1) | v_FIFO_FULL_MASK(1));
824                 hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_SW_AUD_FIFO_RST, v_SW_AUD_FIFO_RST(1));
825         }
826
827         hdmi_msk_reg(hdmi_dev, AUD_INPUTCLKFS, m_LFS_FACTOR, v_LFS_FACTOR(mclk_fs));
828
829         //Set N value
830         hdmi_msk_reg(hdmi_dev, AUD_N3, m_AUD_N3, v_AUD_N3(N >> 16));
831         hdmi_writel(hdmi_dev, AUD_N2, (N >> 8) & 0xff);
832         hdmi_writel(hdmi_dev, AUD_N1, N & 0xff);
833         //Set Automatic CTS generation
834         hdmi_msk_reg(hdmi_dev, AUD_CTS3, m_CTS_MANUAL, v_CTS_MANUAL(0));
835
836         hdmi_msk_reg(hdmi_dev, MC_CLKDIS, m_AUDCLK_DISABLE, v_AUDCLK_DISABLE(0));
837         rk3288_hdmi_config_aai(hdmi_drv, audio);
838
839         return 0;
840 }
841
842 void rk3288_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
843 {
844         hdmi_dbg(hdmi_drv->dev, "[%s] %d\n", __FUNCTION__, enable);
845         if(enable == 0) {
846                 rk3288_hdmi_av_mute(hdmi_drv, 1);
847         }
848         else {
849                 if(hdmi_drv->pwr_mode == LOWER_PWR)
850                         rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
851                 /* disable blue screen transmission after turning on all necessary blocks*/
852                 rk3288_hdmi_video_forceOutput(hdmi_drv, 0);
853                 rk3288_hdmi_av_mute(hdmi_drv, 0);
854         }
855 }
856
857 int rk3288_hdmi_insert(struct hdmi *hdmi_drv)
858 {
859         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
860
861         /* report HPD state to HDCP (after configuration) */
862         hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
863
864         return 0;
865 }
866
867 int rk3288_hdmi_removed(struct hdmi *hdmi_drv)
868 {
869         rk3288_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
870         dev_printk(KERN_INFO , hdmi_drv->dev , "Removed.\n");
871         return 0;
872 }
873
874 int rk3288_hdmi_initial(struct hdmi *hdmi_drv)
875 {
876         int rc = HDMI_ERROR_SUCESS;
877
878         hdmi_drv->insert = rk3288_hdmi_insert;
879         hdmi_drv->remove = rk3288_hdmi_removed;
880         hdmi_drv->control_output = rk3288_hdmi_control_output;
881         hdmi_drv->config_video = rk3288_hdmi_config_video;
882         hdmi_drv->config_audio = rk3288_hdmi_config_audio;
883         hdmi_drv->detect_hotplug = rk3288_hdmi_detect_hotplug;
884         hdmi_drv->read_edid = rk3288_hdmi_read_edid;
885
886         if(hdmi_drv->hdcp_power_on_cb)
887                 rc = hdmi_drv->hdcp_power_on_cb();
888
889         return rc;
890 }
891
892 irqreturn_t hdmi_irq(int irq, void *priv)
893 {
894         struct hdmi *hdmi_drv = (struct hdmi *)priv;
895         struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
896         int phy_int = 0, i2cm_int = 0, phy_i2cm_int = 0, cec_int = 0;
897         int aud_dma_int = 0;
898
899         //read interrupt
900         phy_int = hdmi_readl(hdmi_dev, IH_PHY_STAT0);
901         i2cm_int = hdmi_readl(hdmi_dev, IH_I2CM_STAT0);
902         phy_i2cm_int = hdmi_readl(hdmi_dev, IH_I2CMPHY_STAT0);
903         cec_int = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
904         aud_dma_int = hdmi_readl(hdmi_dev, IH_AHBDMAAUD_STAT0);
905         //hdcp_int = hdmi_readl(hdmi_dev, A_APIINTSTAT);
906
907         //clear interrupt
908         hdmi_writel(hdmi_dev, IH_PHY_STAT0, phy_int);
909         hdmi_writel(hdmi_dev, IH_I2CM_STAT0, i2cm_int);
910         hdmi_writel(hdmi_dev, IH_I2CMPHY_STAT0, phy_i2cm_int);
911         hdmi_writel(hdmi_dev, IH_CEC_STAT0, cec_int);
912         hdmi_writel(hdmi_dev, IH_AHBDMAAUD_STAT0, aud_dma_int);
913         //hdmi_writel(hdmi_dev, A_APIINTCLR, hdcp_int);
914
915         //HPD
916         if(phy_int & m_HPD) {
917                 if(hdmi_drv->state == HDMI_SLEEP)
918                         hdmi_drv->state = WAIT_HOTPLUG;
919                 queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, msecs_to_jiffies(5));
920         }
921
922         //I2CM write or read result
923         if(i2cm_int & (m_SCDC_READREQ | m_I2CM_DONE | m_I2CM_ERROR)) {
924                 spin_lock(&hdmi_drv->irq_lock);
925                 hdmi_dev->i2cm_int = i2cm_int;
926                 spin_unlock(&hdmi_drv->irq_lock);
927         }
928
929         //PHY I2CM write or read result
930         if(phy_i2cm_int & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
931                 mutex_lock(&hdmi_dev->int_mutex);
932                 hdmi_dev->phy_i2cm_int = phy_i2cm_int;
933                 mutex_unlock(&hdmi_dev->int_mutex);
934         }
935
936         //CEC
937         if(cec_int) {   //TODO Daisen wait to modify
938         }
939
940         //HDCP
941         if(hdmi_drv->hdcp_irq_cb)
942                 hdmi_drv->hdcp_irq_cb(i2cm_int);
943
944         return IRQ_HANDLED;
945 }
946