Merge branch 'develop-3.0' of ssh://10.10.10.29/rk/kernel into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / mfd / rk616-vif.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/slab.h>
4 #include <linux/mfd/rk616.h>
5
6
7
8 extern int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac);
9 extern int rk616_pll_pwr_down(struct mfd_rk616 *rk616,int id);
10
11
12 /*rk616 video interface config*/
13
14  int rk616_vif_disable(struct mfd_rk616 *rk616,int id)
15 {
16         u32 val = 0;
17         int ret = 0;
18         
19         if(id == 0) //video interface 0
20         {
21                         val = (VIF0_EN << 16); //disable vif0
22                         ret = rk616->write_dev(rk616,VIF0_REG0,&val);
23                 
24         }
25         else       //vide0 interface 1
26         {
27                         val = (VIF0_EN << 16); //disabl VIF1
28                         ret = rk616->write_dev(rk616,VIF1_REG0,&val);
29                         
30         }
31         
32         msleep(21);
33         
34         if(id == 0) //video interface 0
35         {
36                         val = VIF0_CLK_GATE | (VIF0_CLK_GATE << 16); //gating vif0
37                         ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
38                 
39         }
40         else       //vide0 interface 1
41         {
42                         val = VIF1_CLK_GATE | (VIF1_CLK_GATE << 16); //gating vif1
43                         ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
44                         
45         }
46
47         rk616_dbg(rk616->dev,"rk616 vif%d disable\n",id);
48         
49         return 0;
50 }
51
52
53 int rk616_vif_enable(struct mfd_rk616 *rk616,int id)
54 {
55         u32 val = 0;
56         u32 offset = 0;
57         int ret;
58
59         
60         if(id == 0)
61         {
62                 val = (VIF0_CLK_BYPASS << 16) | (VIF0_CLK_GATE << 16);
63                 offset = 0;
64         }
65         else
66         {
67                 val = (VIF1_CLK_BYPASS << 16) |(VIF1_CLK_GATE << 16);
68                 offset = 0x18;
69         }
70
71         ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
72         
73         val = 0;
74         val |= (VIF0_DDR_CLK_EN <<16) | (VIF0_DDR_PHASEN_EN << 16) | (VIF0_DDR_MODE_EN << 16)|
75                 (VIF0_EN <<16) | VIF0_EN; //disable ddr mode,enable VIF
76         ret = rk616->write_dev(rk616,VIF0_REG0 + offset,&val);
77
78         
79         rk616_dbg(rk616->dev,"rk616 vif%d enable\n",id);
80
81         return 0;
82         
83 }
84 static int  rk616_vif_bypass(struct mfd_rk616 *rk616,int id)
85 {
86         u32 val = 0;
87         int ret;
88
89         if(id == 0)
90         {
91                 val = (VIF0_CLK_BYPASS | VIF0_CLK_BYPASS << 16);
92         }
93         else
94         {
95                 val = (VIF1_CLK_BYPASS | VIF1_CLK_BYPASS << 16);
96         }
97
98         ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
99
100         rk616_dbg(rk616->dev,"rk616 vif%d bypass\n",id);
101         return 0;
102 }
103
104 static bool pll_sel_mclk12m(struct mfd_rk616 *rk616,int pll_id)
105 {
106         if(pll_id == 0) //pll0
107         {
108                 if(rk616->route.pll0_clk_sel == PLL0_CLK_SEL(MCLK_12M))
109                         return true;
110                 else
111                         return false;
112         }
113         else
114         {
115                 if(rk616->route.pll1_clk_sel == PLL1_CLK_SEL(MCLK_12M))
116                         return  true;
117                 else
118                         return false;   
119         }
120
121         return false;
122 }
123
124
125
126 int rk616_vif_cfg(struct mfd_rk616 *rk616,rk_screen *screen,int id)
127 {
128         int ret = 0;
129         u32 val = 0;
130         int offset = 0;
131         int pll_id;
132         bool pll_use_mclk12m = false;
133         
134         if(id == 0) //video interface 0
135         {
136                 if(!rk616->route.vif0_en)
137                 {
138                         rk616_vif_disable(rk616,id);
139                         return 0;
140                 }
141                 offset = 0;
142                 pll_id = rk616->route.vif0_clk_sel;
143         }
144         else       //vide0 interface 1
145         {
146                 if(!rk616->route.vif1_en)
147                 {
148                         rk616_vif_disable(rk616,id);
149                         return 0;
150                 }
151                 offset = 0x18;
152                 pll_id = (rk616->route.vif1_clk_sel >> 6);
153                 
154         }
155
156         pll_use_mclk12m = pll_sel_mclk12m(rk616,pll_id);
157         
158         if(pll_use_mclk12m)
159         {
160                 clk_set_rate(rk616->mclk, 12000000);
161         }
162
163         
164         if(!screen)
165         {
166                 dev_err(rk616->dev,"%s:screen is null.........\n",__func__);
167                 return -EINVAL;
168         }
169
170
171         rk616_vif_disable(rk616,id);
172         if( (screen->x_res == 1920) && (screen->y_res == 1080))
173         {
174                 if(pll_use_mclk12m)
175                         //rk616_pll_set_rate(rk616,pll_id,0xc11025,0x200000);
176                         rk616_pll_set_rate(rk616,pll_id,0x028853de,0);
177                 else
178                         rk616_pll_set_rate(rk616,pll_id,0x02bf5276,0);
179                 
180                 val = (0xc1) | (0x01 <<16);
181         }
182         else if((screen->x_res == 1280) && (screen->y_res == 720))
183         {
184                 if(pll_use_mclk12m)
185                         //rk616_pll_set_rate(rk616,pll_id,0x01811025,0x200000);
186                         rk616_pll_set_rate(rk616,pll_id,0x0288418c,0);
187                 else
188                         rk616_pll_set_rate(rk616,pll_id,0x1422014,0);
189                 
190                 val = (0xc1) | (0x01 <<16);
191         
192         }
193         else if((screen->x_res == 720))
194         {
195                 if(pll_use_mclk12m )
196                 {
197                         rk616_pll_set_rate(rk616,pll_id,0x0306510e,0);
198                 }
199                 else
200                         rk616_pll_set_rate(rk616,pll_id,0x1c13015,0);
201                 
202                 val = (0x1) | (0x01 <<16);
203         }
204
205         
206         
207         ret = rk616->write_dev(rk616,VIF0_REG1 + offset,&val);
208
209         val = (screen->hsync_len << 16) | (screen->hsync_len + screen->left_margin + 
210                 screen->right_margin + screen->x_res);
211         ret = rk616->write_dev(rk616,VIF0_REG2 + offset,&val);
212
213         
214         val = ((screen->hsync_len + screen->left_margin + screen->x_res)<<16) |
215                 (screen->hsync_len + screen->left_margin);
216         ret = rk616->write_dev(rk616,VIF0_REG3 + offset,&val);
217
218         val = (screen->vsync_len << 16) | (screen->vsync_len + screen->upper_margin + 
219                 screen->lower_margin + screen->y_res);
220         ret = rk616->write_dev(rk616,VIF0_REG4 + offset,&val);
221
222
223         val = ((screen->vsync_len + screen->upper_margin + screen->y_res)<<16) |
224                 (screen->vsync_len + screen->upper_margin);
225         ret = rk616->write_dev(rk616,VIF0_REG5 + offset,&val);
226
227         if(id == 0)
228         {
229                 val = VIF0_SYNC_EN | (VIF0_SYNC_EN << 16);
230                 rk616->write_dev(rk616,CRU_IO_CON0,&val);
231         }
232         else
233         {
234                 val = VIF1_SYNC_EN | (VIF1_SYNC_EN << 16);
235                 rk616->write_dev(rk616,CRU_IO_CON0,&val);
236         }
237         rk616_vif_enable(rk616,id);
238         
239         return ret;
240         
241 }
242
243
244 static int rk616_scaler_disable(struct mfd_rk616 *rk616)
245 {
246         u32 val = 0;
247         int ret;
248         val &= (~SCL_EN);       //disable scaler
249         val |= (SCL_EN<<16);
250         ret = rk616->write_dev(rk616,SCL_REG0,&val);
251         rk616_dbg(rk616->dev,"rk616 scaler disable\n");
252         return 0;
253 }
254
255 int rk616_scaler_cfg(struct mfd_rk616 *rk616,rk_screen *screen)
256 {
257         u32 scl_hor_mode,scl_ver_mode;
258         u32 scl_v_factor,scl_h_factor;
259         u32 scl_reg0_value,scl_reg1_value,scl_reg2_value;                //scl_con,scl_h_factor,scl_v_factor,
260         u32 scl_reg3_value,scl_reg4_value,scl_reg5_value,scl_reg6_value; //dsp_frame_hst,dsp_frame_vst,dsp_timing,dsp_act_timing
261         u32 scl_reg7_value,scl_reg8_value;                               //dsp_hbor ,dsp_vbor
262         u32 dst_frame_hst,dst_frame_vst;                    //ʱÐò»º´æ
263         u32 dst_vact_st;
264
265         u32 dsp_htotal,dsp_hs_end,dsp_hact_st,dsp_hact_end; //scalerÊä³öµÄtiming²ÎÊý
266         u32 dsp_vtotal,dsp_vs_end,dsp_vact_st,dsp_vact_end; 
267         u32 dsp_hbor_end,dsp_hbor_st,dsp_vbor_end,dsp_vbor_st;
268         u32 src_w,src_h,src_htotal,dst_w,dst_h,src_vact_st;
269         u16 bor_right = 0;
270         u16 bor_left = 0;
271         u16 bor_up = 0;
272         u16 bor_down = 0;
273         u8 hor_down_mode = 0;  //1:average,0:bilinear
274         u8 ver_down_mode = 0;
275         u8 bic_coe_sel = 2;
276         rk_screen *src;
277         rk_screen *dst;
278         int pll_id;
279
280         struct rk616_route *route = &rk616->route;
281
282
283         if(!route->scl_en)
284         {
285                 rk616_scaler_disable(rk616);
286                 return 0;
287         }
288         
289         
290         dst = screen;
291         if(!dst)
292         {
293                 dev_err(rk616->dev,"%s:screen is null!\n",__func__);
294                 return -EINVAL;
295         }
296
297         if(route->scl_bypass)
298         {
299                 src = dst;
300                 dst->pll_cfg_val = 0x01422014;
301                 dst->frac = 0;
302         }
303         else
304                 src = screen->ext_screen;
305         
306         if(route->sclk_sel == SCLK_SEL(SCLK_SEL_PLL0))
307                 pll_id = 0;
308         else
309                 pll_id = 1;
310
311         rk616_scaler_disable(rk616);
312         rk616_pll_set_rate(rk616,pll_id,dst->pll_cfg_val,dst->frac);
313         dst_frame_vst = dst->scl_vst;
314         dst_frame_hst = dst->scl_hst;
315
316
317 #if 1
318
319         src_htotal = src->hsync_len + src->left_margin + src->x_res + src->right_margin;
320         src_vact_st = src->vsync_len + src->upper_margin  ;
321         dst_vact_st = dst->vsync_len + dst->upper_margin;
322
323         dsp_htotal    = dst->hsync_len + dst->left_margin + dst->x_res + dst->right_margin; //dst_htotal ;
324         dsp_hs_end    = dst->hsync_len;
325
326         dsp_vtotal    = dst->vsync_len + dst->upper_margin + dst->y_res + dst->lower_margin;
327         dsp_vs_end    = dst->vsync_len;
328
329         dsp_hbor_end  = dst->hsync_len + dst->left_margin + dst->x_res;
330         dsp_hbor_st   = dst->hsync_len + dst->left_margin  ;
331         dsp_vbor_end  = dst->vsync_len + dst->upper_margin + dst->y_res; //dst_vact_end ;
332         dsp_vbor_st   = dst_vact_st  ;
333
334         dsp_hact_st   = dsp_hbor_st  + bor_left;
335         dsp_hact_end  = dsp_hbor_end - bor_right; 
336         dsp_vact_st   = dsp_vbor_st  + bor_up;
337         dsp_vact_end  = dsp_vbor_end - bor_down; 
338
339         src_w = src->x_res;
340         src_h = src->y_res;
341         dst_w = dsp_hact_end - dsp_hact_st ;
342         dst_h = dsp_vact_end - dsp_vact_st ;
343
344         if(src_w > dst_w)         //ÅжÏhorµÄËõ·Åģʽ 0£ºno_scl 1£ºscl_up 2£ºscl_down
345         {
346                 scl_hor_mode = 0x2;   //scl_down
347                 if(hor_down_mode == 0)//bilinear
348                 {
349                         if((src_w-1)/(dst_w-1) > 2)
350                         {
351                                 scl_h_factor = ((src_w-1)<<14)/(dst_w-1);
352                         }
353                         else
354                                 scl_h_factor = ((src_w-2)<<14)/(dst_w-1);
355                 }
356                 else  //average
357                 {
358                         scl_h_factor = ((dst_w)<<16)/(src_w-1);
359                 }
360         }
361         else if(src_w == dst_w)
362         {
363                 scl_hor_mode = 0x0;   //no_Scl
364                 scl_h_factor = 0x0;
365         } 
366         else 
367         {
368                 scl_hor_mode = 0x1;   //scl_up
369                 scl_h_factor = ((src_w-1)<<16)/(dst_w-1);
370         } 
371     
372         if(src_h > dst_h)         //ÅжÏverµÄËõ·Åģʽ 0£ºno_scl 1£ºscl_up 2£ºscl_down
373         {
374                 scl_ver_mode = 0x2;   //scl_down
375                 if(ver_down_mode == 0)//bilinearhor_down_mode,u8 ver_down_mode
376                 {
377                         if((src_h-1)/(dst_h-1) > 2)
378                         {
379                                 scl_v_factor = ((src_h-1)<<14)/(dst_h-1);
380                         }
381                         else
382                                 scl_v_factor = ((src_h-2)<<14)/(dst_h-1);
383                 }
384                 else
385                 {
386                         scl_v_factor = ((dst_h)<<16)/(src_h-1);
387                 }
388         }
389         else if(src_h == dst_h)
390         {
391                 scl_ver_mode = 0x0;   //no_Scl
392                 scl_v_factor = 0x0;
393         }
394         else 
395         {
396                 scl_ver_mode = 0x1;   //scl_up
397                 scl_v_factor = ((src_h-1)<<16)/(dst_h-1);
398         }
399
400         //control   register0 
401         scl_reg0_value = (0x1ff<<16) | SCL_EN | (scl_hor_mode<<1) |
402                         (scl_ver_mode<<3) | (bic_coe_sel<<5) | 
403                         (hor_down_mode<<7) | (ver_down_mode<<8) ;
404         //factor    register1 
405         scl_reg1_value = (scl_v_factor << 16) | scl_h_factor ;
406         //dsp_frame register2 
407         scl_reg2_value = dst_frame_vst<<16 | dst_frame_hst ;
408         //dsp_h     register3
409         scl_reg3_value = dsp_hs_end<<16 | dsp_htotal ;
410         //dsp_hact  register4
411         scl_reg4_value = dsp_hact_end <<16 | dsp_hact_st ;
412         //dsp_v     register5
413         scl_reg5_value = dsp_vs_end<<16 | dsp_vtotal ;
414         //dsp_vact  register6
415         scl_reg6_value = dsp_vact_end<<16 | dsp_vact_st ;
416         //hbor      register7
417         scl_reg7_value = dsp_hbor_end<<16 | dsp_hbor_st ;
418         //vbor      register8
419         scl_reg8_value = dsp_vbor_end<<16 | dsp_vbor_st ;
420  
421         rk616->write_dev(rk616,SCL_REG1,&scl_reg1_value);  
422         rk616->write_dev(rk616,SCL_REG2,&scl_reg2_value);  
423         rk616->write_dev(rk616,SCL_REG3,&scl_reg3_value);  
424         rk616->write_dev(rk616,SCL_REG4,&scl_reg4_value);  
425         rk616->write_dev(rk616,SCL_REG5,&scl_reg5_value);  
426         rk616->write_dev(rk616,SCL_REG6,&scl_reg6_value);  
427         rk616->write_dev(rk616,SCL_REG7,&scl_reg7_value);  
428         rk616->write_dev(rk616,SCL_REG8,&scl_reg8_value);
429         rk616->write_dev(rk616,SCL_REG0,&scl_reg0_value); 
430
431         rk616_dbg(rk616->dev,"rk616 scaler enable\n");
432 #endif
433         return 0;
434         
435 }
436
437
438 static int rk616_dual_input_cfg(struct mfd_rk616 *rk616,rk_screen *screen,
439                                         bool enable)
440 {
441         struct rk616_platform_data *pdata = rk616->pdata;
442         struct rk616_route *route = &rk616->route;
443         
444         route->vif0_bypass = VIF0_CLK_BYPASS;
445         route->vif0_en     = 0;
446         route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
447         route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
448         route->pll1_clk_sel = PLL1_CLK_SEL(LCD1_DCLK);
449         route->vif1_clk_sel = VIF1_CLKIN_SEL(VIF_CLKIN_SEL_PLL1);
450         route->hdmi_sel     = HDMI_IN_SEL(HDMI_IN_SEL_VIF1);
451         route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF1);
452         if(enable)  //hdmi plug in
453         {
454                 route->vif1_bypass  = 0;
455                 route->vif1_en      = 1;
456                 
457         }
458         else  //hdmi plug out
459         {
460                 route->vif1_bypass = VIF1_CLK_BYPASS;
461                 route->vif1_en     = 0;
462         }
463
464         route->sclin_sel   = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
465         route->scl_en      = 0;            //dual lcdc, scaler not needed
466         route->dither_sel  = DITHER_IN_SEL(DITHER_SEL_VIF0); //dither from vif0
467         route->lcd1_input  = 1; 
468         
469
470         if(screen->type == SCREEN_RGB)
471         {
472                 route->lvds_en     = 1;
473                 route->lvds_mode   = RGB; //rgb output 
474         }
475         else if(screen->type == SCREEN_LVDS)
476         {
477                 route->lvds_en     = 1;
478                 route->lvds_mode = LVDS;
479                 route->lvds_ch_nr = pdata->lvds_ch_nr;
480         }
481         else if(screen->type == SCREEN_MIPI)
482         {
483                 route->lvds_en = 0;
484         }
485         
486
487         return 0;
488         
489 }
490
491 static int rk616_lcd0_input_lcd1_unused_cfg(struct mfd_rk616 *rk616,rk_screen *screen,
492                                                         bool enable)
493 {
494         struct rk616_platform_data *pdata = rk616->pdata;
495         struct rk616_route *route = &rk616->route;
496         
497         if(enable)  //hdmi plug in
498         {
499                 route->vif0_bypass  = 0;
500                 route->vif0_en      = 1;
501                 route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
502                 route->sclin_sel    = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
503                 route->scl_en       = 1;
504                 route->sclk_sel     = SCLK_SEL(SCLK_SEL_PLL1);
505                 route->dither_sel   = DITHER_IN_SEL(DITHER_SEL_SCL); //dither from sclaer
506                 route->hdmi_sel     = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
507                 route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF0);  
508         }
509         else
510         {
511                 route->vif0_bypass = VIF0_CLK_BYPASS;
512                 route->vif0_en     = 0;
513                 route->sclin_sel   = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
514                 route->scl_en      = 0;
515                 route->dither_sel  = DITHER_IN_SEL(DITHER_SEL_VIF0); //dither from sclaer
516                 route->hdmi_sel    = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
517         }
518         route->pll1_clk_sel = PLL1_CLK_SEL(LCD0_DCLK);
519         route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
520         route->vif1_bypass = VIF1_CLK_BYPASS;
521         route->vif1_en     = 0;
522         route->lcd1_input  = 0;  
523         
524         if(screen->type == SCREEN_RGB)
525         {
526                 route->lvds_en     = 1;
527                 route->lvds_mode   = RGB; //rgb output 
528         }
529         else if(screen->type == SCREEN_LVDS)
530         {
531                 route->lvds_en     = 1;
532                 route->lvds_mode = LVDS;
533                 route->lvds_ch_nr = pdata->lvds_ch_nr;
534         }
535         else if(screen->type == SCREEN_MIPI)
536         {
537                 route->lvds_en = 0;
538         }
539         
540
541         return 0;
542 }
543
544
545 static int rk616_lcd0_input_lcd1_output_cfg(struct mfd_rk616 *rk616,rk_screen *screen,
546                                                         bool enable)
547 {
548         struct rk616_route *route = &rk616->route;
549
550         if(enable)
551         {
552                 route->vif0_bypass  = 0;
553                 route->vif0_en      = 1;
554                 route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
555                 route->sclin_sel    = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
556                 route->scl_en       = 1;
557                 route->sclk_sel     = SCLK_SEL(SCLK_SEL_PLL1);
558                 route->dither_sel   = DITHER_IN_SEL(DITHER_SEL_SCL); //dither from sclaer
559                 route->hdmi_sel     = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
560                 route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF0);
561         }
562         else
563         {
564                 route->vif0_bypass = VIF0_CLK_BYPASS;
565                 route->vif0_en     = 0;
566                 route->sclin_sel   = SCL_IN_SEL(SCL_SEL_VIF0); //from vif0
567                 route->scl_en      = 0;
568                 route->dither_sel  = DITHER_IN_SEL(DITHER_SEL_VIF0); //dither from sclaer
569                 route->hdmi_sel    = HDMI_IN_SEL(HDMI_IN_SEL_VIF0);//from vif0
570                 route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF1);
571         }
572         route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
573         route->pll1_clk_sel = PLL1_CLK_SEL(LCD0_DCLK);
574         route->vif1_bypass = VIF1_CLK_BYPASS;
575         route->vif1_en = 0;
576         route->lcd1_input = 0; //lcd1 as out put
577         route->lvds_en  = 0;
578
579         //route->scl_en      = 0;
580         //route->dither_sel  = DITHER_IN_SEL(DITHER_SEL_VIF0);
581
582         return 0;
583         
584 }
585
586
587 static int rk616_lcd0_unused_lcd1_input_cfg(struct mfd_rk616 *rk616,rk_screen *screen,
588                                                         bool enable)
589 {
590         struct rk616_platform_data *pdata = rk616->pdata;
591         struct rk616_route *route = &rk616->route;
592
593         route->pll0_clk_sel = PLL0_CLK_SEL(LCD1_DCLK);
594         route->pll1_clk_sel = PLL1_CLK_SEL(LCD1_DCLK);
595         route->vif0_bypass = VIF0_CLK_BYPASS;
596         route->vif0_en     = 0;
597         if(enable)
598         {
599                 route->vif1_bypass = 0;
600                 route->vif1_en     = 1;
601                 route->scl_bypass  = 0;
602         }
603         else
604         {
605                 route->vif1_bypass = VIF1_CLK_BYPASS;
606                 route->vif1_en     = 0;
607                 route->scl_bypass = 1; //1:1 scaler
608         }
609         route->vif1_clk_sel = VIF1_CLKIN_SEL(VIF_CLKIN_SEL_PLL1);
610         route->sclin_sel   = SCL_IN_SEL(SCL_SEL_VIF1); //from vif1
611         route->scl_en      = 1;
612         route->sclk_sel    = SCLK_SEL(SCLK_SEL_PLL0);
613         
614         route->dither_sel  = DITHER_IN_SEL(DITHER_SEL_SCL); //dither from sclaer
615         route->hdmi_sel    = HDMI_IN_SEL(HDMI_IN_SEL_VIF1); //from vif1
616         route->hdmi_clk_sel = HDMI_CLK_SEL(HDMI_CLK_SEL_VIF1);
617         route->lcd1_input  = 1;  
618         if(screen->type == SCREEN_RGB)
619         {
620                 route->lvds_en     = 1;
621                 route->lvds_mode   = RGB; //rgb output 
622         }
623         else if(screen->type == SCREEN_LVDS)
624         {
625                 route->lvds_en = 1;
626                 route->lvds_mode = LVDS;
627                 route->lvds_ch_nr = pdata->lvds_ch_nr;
628         }
629         else if(screen->type == SCREEN_MIPI)
630         {
631                 route->lvds_en = 0;
632         }
633         
634
635         return 0;
636 }
637
638 int  rk616_set_router(struct mfd_rk616 *rk616,rk_screen *screen,bool enable)
639 {
640         struct rk616_platform_data *pdata = rk616->pdata;
641         int ret;
642
643         if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == INPUT))
644         {
645                 
646                 ret = rk616_dual_input_cfg(rk616,screen,enable);
647                 rk616_dbg(rk616->dev,"rk616 use dual input for dual display!\n");
648         }
649         else if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == UNUSED))
650         {
651                 ret = rk616_lcd0_input_lcd1_unused_cfg(rk616,screen,enable);
652
653                 rk616_dbg(rk616->dev,
654                         "rk616 use lcd0 as input and lvds/rgb "
655                         "port as output for dual display\n");
656         }
657         else if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == OUTPUT))
658         {
659                 ret = rk616_lcd0_input_lcd1_output_cfg(rk616,screen,enable);
660                 
661                 rk616_dbg(rk616->dev,
662                         "rk616 use lcd0 as input and lcd1 as "
663                         "output for dual display\n");
664         }
665         else if((pdata->lcd0_func == UNUSED) && (pdata->lcd1_func == INPUT))
666         {
667                 ret = rk616_lcd0_unused_lcd1_input_cfg(rk616,screen,enable);
668                 rk616_dbg(rk616->dev,
669                         "rk616 use lcd1 as input and lvds/rgb as "
670                         "output for dual display\n");
671         }
672         else
673         {
674                 dev_err(rk616->dev,
675                         "invalid configration,please check your"
676                         "rk616_platform_data setting in your board file!\n");
677                 return -EINVAL;
678         }
679
680         return ret ;
681         
682 }
683
684
685
686
687 static int rk616_router_cfg(struct mfd_rk616 *rk616)
688 {
689         u32 val;
690         int ret;
691         struct rk616_route *route = &rk616->route;
692         val = (route->pll0_clk_sel) | (route->pll1_clk_sel) |
693                 PLL1_CLK_SEL_MASK | PLL0_CLK_SEL_MASK; //pll1 clk from lcdc1_dclk,pll0 clk from lcdc0_dclk,mux_lcdx = lcdx_clk
694         ret = rk616->write_dev(rk616,CRU_CLKSEL0_CON,&val);
695         
696         val = (route->sclk_sel) | SCLK_SEL_MASK;
697         ret = rk616->write_dev(rk616,CRU_CLKSEL1_CON,&val);
698         
699         val = (SCL_IN_SEL_MASK) | (DITHER_IN_SEL_MASK) | (HDMI_IN_SEL_MASK) | 
700                 (VIF1_CLKIN_SEL_MASK) | (VIF0_CLKIN_SEL_MASK) | (VIF1_CLK_BYPASS << 16) | 
701                 (VIF0_CLK_BYPASS << 16) |(route->sclin_sel) | (route->dither_sel) | 
702                 (route->hdmi_sel) | (route->vif1_bypass) | (route->vif0_bypass) |
703                 (route->vif1_clk_sel)| (route->vif0_clk_sel); 
704         ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
705         val = route->hdmi_clk_sel;
706         ret = rk616->write_dev_bits(rk616,CRU_CFGMISC_CON,HDMI_CLK_SEL_MASK,&val);
707
708         return ret;
709 }
710
711
712 static int rk616_dither_cfg(struct mfd_rk616 *rk616,rk_screen *screen,bool enable)
713 {
714         u32 val = 0;
715         int ret = 0;
716         val = FRC_DCLK_INV | (FRC_DCLK_INV << 16);
717         if((screen->face != OUT_P888) && enable)  //enable frc dither if the screen is not 24bit
718                 val |= FRC_DITHER_EN | (FRC_DITHER_EN << 16);
719                 //val |= (FRC_DITHER_EN << 16);
720         else
721                 val |= (FRC_DITHER_EN << 16);
722         ret = rk616->write_dev(rk616,FRC_REG,&val);
723
724         return 0;
725         
726 }
727
728 int rk616_display_router_cfg(struct mfd_rk616 *rk616,rk_screen *screen,bool enable)
729 {
730         int ret;
731         rk_screen *hdmi_screen = screen->ext_screen;
732         ret = rk616_set_router(rk616,screen,enable);
733         if(ret < 0)
734                 return ret;
735         ret = rk616_router_cfg(rk616);
736         ret = rk616_vif_cfg(rk616,hdmi_screen,0);
737         ret = rk616_vif_cfg(rk616,hdmi_screen,1);
738         ret = rk616_scaler_cfg(rk616,screen);                   
739         ret = rk616_dither_cfg(rk616,screen,enable);
740         return 0;
741         
742 }
743
744 int rk616_set_vif(struct mfd_rk616 *rk616,rk_screen *screen,bool connect)
745 {
746         struct rk616_platform_data *pdata;
747         if(!rk616)
748         {
749                 printk(KERN_ERR "%s:mfd rk616 is null!\n",__func__);
750                 return -1;
751         }
752         else
753         {
754                 pdata = rk616->pdata;
755         }
756
757         if(!connect)
758         {
759                 rk616_vif_disable(rk616,0);
760                 rk616_vif_disable(rk616,1);
761                 clk_set_rate(rk616->mclk, 11289600); 
762                 return 0;
763         }
764 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
765         return 0;
766 #else
767         if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == INPUT))
768         {
769                 
770                 rk616_dual_input_cfg(rk616,screen,connect);
771                 rk616_dbg(rk616->dev,"rk616 use dual input for dual display!\n");
772         }
773         else if((pdata->lcd0_func == INPUT) && (pdata->lcd1_func == UNUSED))
774         {
775                 rk616_lcd0_input_lcd1_unused_cfg(rk616,screen,connect);
776                 rk616_dbg(rk616->dev,"rk616 use lcd0 input for hdmi display!\n");
777         }
778         rk616_router_cfg(rk616);
779         rk616_vif_cfg(rk616,screen,0);
780         rk616_vif_cfg(rk616,screen,1);
781         rk616_scaler_disable(rk616);
782 #endif
783         
784         return 0;
785         
786         
787 }
788
789
790
791