Merge tag 'lsk-android-14.05' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / transmitter / rk610_lcd.c
1 #include <linux/fb.h>
2 #include <linux/delay.h>
3 #include <mach/gpio.h>
4 #include <mach/iomux.h>
5 #include <mach/board.h>
6 #include "rk610_lcd.h"
7 #include <linux/mfd/rk610_core.h>
8 #include <linux/rk_fb.h>
9 #include "../hdmi/rk_hdmi.h"
10
11 static struct rk610_lcd_info *g_lcd_inf = NULL;
12 //static int rk610_scaler_read_p0_reg(struct i2c_client *client, char reg, char *val)
13 //{
14         //return i2c_master_reg8_recv(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
15 //}
16
17 static int rk610_scaler_write_p0_reg(struct i2c_client *client, char reg, char *val)
18 {
19         return i2c_master_reg8_send(client, reg, val, 1, 100*1000) > 0? 0: -EINVAL;
20 }
21 static void rk610_scaler_pll_enable(struct i2c_client *client)
22 {
23     char c;
24     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
25
26     g_lcd_inf->scl_inf.pll_pwr = ENABLE;
27     
28     c = S_PLL_PWR(0)|S_PLL_RESET(0)|S_PLL_BYPASS(0);
29         rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);
30 }
31 static void rk610_scaler_pll_disable(struct i2c_client *client)
32 {
33     char c;
34     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
35     
36     g_lcd_inf->scl_inf.pll_pwr = DISABLE;
37
38     c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);
39         rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);
40 }
41 static void rk610_scaler_enable(struct i2c_client *client)
42 {
43     char c;
44     bool den_inv = 0,hv_sync_inv = 0,clk_inv = 0;
45     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
46     g_lcd_inf->scl_inf.scl_pwr = ENABLE;
47     #if defined(CONFIG_HDMI_DUAL_DISP) || defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
48     if(g_lcd_inf->screen !=NULL){
49         den_inv = g_lcd_inf->screen->s_den_inv;
50         hv_sync_inv = g_lcd_inf->screen->s_hv_sync_inv;
51         clk_inv = g_lcd_inf->screen->s_clk_inv;
52     }
53     #endif
54     c= SCL_BYPASS(0) |SCL_DEN_INV(den_inv) |SCL_H_V_SYNC_INV(hv_sync_inv) |SCL_OUT_CLK_INV(clk_inv) |SCL_ENABLE(ENABLE);  
55         rk610_scaler_write_p0_reg(client, SCL_CON0, &c);
56 }
57 static void rk610_scaler_disable(struct i2c_client *client)
58 {
59     char c;
60     bool den_inv = 0,hv_sync_inv = 0,clk_inv = 0;
61     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
62     
63     g_lcd_inf->scl_inf.scl_pwr = DISABLE;
64     #if defined(CONFIG_HDMI_DUAL_DISP) || defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
65     if(g_lcd_inf->screen !=NULL){
66         den_inv = g_lcd_inf->screen->s_den_inv;
67         hv_sync_inv = g_lcd_inf->screen->s_hv_sync_inv;
68         clk_inv = g_lcd_inf->screen->s_clk_inv;
69     }
70     #endif
71     c= SCL_BYPASS(1) |SCL_DEN_INV(den_inv) |SCL_H_V_SYNC_INV(hv_sync_inv) |SCL_OUT_CLK_INV(clk_inv) |SCL_ENABLE(DISABLE); 
72     rk610_scaler_write_p0_reg(client, SCL_CON0, &c);
73 }
74
75 static int rk610_output_config(struct i2c_client *client,struct rk_screen *screen,int mode)
76 {
77     char c=0;
78     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
79      if(SCREEN_LVDS == screen->type){
80         if(mode == LCD_OUT_SCL || mode == LCD_OUT_BYPASS){
81                 c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(1) |LVDS_PLL_PWR_PIN(0) \
82                     |LVDS_LANE_IN_FORMAT(DATA_D0_MSB) \
83                     |LVDS_OUTPUT_FORMAT(screen->lvds_format) | LVDS_BIASE_PWR(1); 
84 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL) && defined(CONFIG_HDMI_RK610)
85                 c |=  LVDS_INPUT_SOURCE(FROM_LCD1);
86 #else
87                 c |=  LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL);
88 #endif                
89                 rk610_scaler_write_p0_reg(client, LVDS_CON0, &c);
90                 c = LCD1_OUT_ENABLE(LCD1_AS_IN);
91                 rk610_scaler_write_p0_reg(client, LCD1_CON, &c);
92                 c = LVDS_OUT_ENABLE(0x0) |LVDS_TX_PWR_ENABLE(0x0); 
93                 rk610_scaler_write_p0_reg(client, LVDS_CON1, &c);
94             }
95             else{
96                     c = LVDS_OUT_CLK_PIN(0) |LVDS_OUT_CLK_PWR_PIN(0) |LVDS_PLL_PWR_PIN(1) \
97                         |LVDS_LANE_IN_FORMAT(DATA_D0_MSB)  \
98                         |LVDS_OUTPUT_FORMAT(screen->lvds_format) | LVDS_BIASE_PWR(0); 
99 #if defined(CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL) && defined(CONFIG_HDMI_RK610)
100                     c |=  LVDS_INPUT_SOURCE(FROM_LCD1);
101 #else
102                     c |=  LVDS_INPUT_SOURCE(FROM_LCD0_OR_SCL);
103 #endif                
104                     rk610_scaler_write_p0_reg(client, LVDS_CON0, &c);
105                     c = LCD1_OUT_ENABLE(LCD1_AS_IN);
106                     rk610_scaler_write_p0_reg(client, LCD1_CON, &c);
107                     c = LVDS_OUT_ENABLE(0xf) |LVDS_TX_PWR_ENABLE(0xf); 
108                     rk610_scaler_write_p0_reg(client, LVDS_CON1, &c);
109              
110             }
111         }else if(SCREEN_RGB == screen->type){
112             if(mode == LCD_OUT_SCL || mode == LCD_OUT_BYPASS){
113             c = LCD1_OUT_ENABLE(LCD1_AS_OUT) | LCD1_OUT_SRC((mode == LCD_OUT_SCL)?LCD1_FROM_SCL : LCD1_FROM_LCD0);
114                 rk610_scaler_write_p0_reg(client, LCD1_CON, &c);
115             }
116             else {
117             c = LCD1_OUT_ENABLE(LCD1_AS_IN);
118                 rk610_scaler_write_p0_reg(client, LCD1_CON, &c);
119             }
120         }
121         return 0;
122 }
123 #if defined(CONFIG_HDMI_DUAL_DISP) || defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
124 static int rk610_scaler_pll_set(struct i2c_client *client,struct rk_screen *screen,u32 clkin )
125 {
126     char c=0;
127     char M=0,N=0,OD=0;
128     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
129         /***************SET SCALER PLL FROM CLKIN ,DIV 0*/
130     if(screen->s_pixclock != 0){
131         OD = (screen->s_pixclock)&0x3;
132         N = (screen->s_pixclock >>4)&0xf;
133         M = (screen->s_pixclock >>8)&0xff;
134     }else {
135         RK610_ERR(&client->dev,"RK610 Scaler pll not support rate \n");
136     }
137     c = S_PLL_FROM_DIV<<3 | S_PLL_DIV(0);
138         rk610_scaler_write_p0_reg(client, CLOCK_CON0, &c);
139     
140     c = S_DIV_N(N)| S_DIV_OD(OD);
141         rk610_scaler_write_p0_reg(client, S_PLL_CON0, &c);
142     c = S_DIV_M(M);
143     rk610_scaler_write_p0_reg(client, S_PLL_CON1, &c);
144     rk610_scaler_pll_enable(client);
145         return 0;
146 }
147
148
149 static int  scale_hv_factor(struct i2c_client *client ,u32 Hin_act, u32 Hout_act, u32 Vin_act, u32 Vout_act)
150    {
151     char c;
152         u32 hfactor_f,vfactor_f,scl_factor_f;
153         int  hfactor;
154         int  vfactor;
155         struct scl_hv_info  HV2;
156         hfactor_f = ((Hin_act-1)*4096)/(Hout_act-1);
157     if(hfactor_f==4096)
158             {hfactor = 0x1000;}
159         else if(hfactor_f>(int)hfactor_f)
160                 {hfactor = (int)hfactor_f+1;}
161         else
162                 {hfactor = (int)hfactor_f;}
163           
164         scl_factor_f = Vin_act/Vout_act;
165         if(scl_factor_f<2)
166             {vfactor_f = ((Vin_act-1)*4096)/(Vout_act-1);}
167         else
168                 {vfactor_f = ((Vin_act-2)*4096)/(Vout_act-1);} 
169         if(vfactor_f==4096)
170             {vfactor = 0x1000;}
171         else if(vfactor_f>(int)vfactor_f)
172                 {vfactor = (int)vfactor_f+1;}
173         else
174                 {vfactor = (int)vfactor_f;}
175           
176     HV2.scl_h= hfactor;
177     HV2.scl_v= vfactor; 
178            /*       SCL FACTOR          */
179     c = SCL_H_FACTOR_LSB(HV2.scl_h);
180         rk610_scaler_write_p0_reg(client, SCL_CON1, &c);
181     c = SCL_H_FACTOR_MSB(HV2.scl_h);
182         rk610_scaler_write_p0_reg(client, SCL_CON2, &c);
183
184     c = SCL_V_FACTOR_LSB(HV2.scl_v);
185         rk610_scaler_write_p0_reg(client, SCL_CON3, &c);
186     c = SCL_V_FACTOR_MSB(HV2.scl_v);
187         rk610_scaler_write_p0_reg(client, SCL_CON4, &c);
188         return 0;
189    }
190
191 static int rk610_scaler_fator_config(struct i2c_client *client ,struct rk_screen *screen)
192 {
193     switch(screen->hdmi_resolution){
194         case HDMI_1920x1080p_60Hz:
195         case HDMI_1920x1080p_50Hz:
196             rk610_scaler_pll_set(client,screen,148500000);
197             /***************set scaler factor********************/
198             scale_hv_factor(client,1920,screen->x_res,1080,screen->y_res);
199             break;
200         case HDMI_1280x720p_60Hz:
201         case HDMI_1280x720p_50Hz:
202             rk610_scaler_pll_set(client,screen,74250000);
203             /***************set scaler factor********************/
204             scale_hv_factor(client,1280,screen->x_res,720,screen->y_res);
205         break;
206         case HDMI_720x576p_50Hz_16_9:
207         case HDMI_720x576p_50Hz_4_3:
208             rk610_scaler_pll_set(client,screen,27000000);
209             /***************set scaler factor********************/
210             scale_hv_factor(client,720,screen->x_res,576,screen->y_res);
211             break;
212         case HDMI_720x480p_60Hz_16_9:
213         case HDMI_720x480p_60Hz_4_3:
214             rk610_scaler_pll_set(client,screen,27000000);
215             /***************set scaler factor********************/
216             scale_hv_factor(client,720,screen->x_res,480,screen->y_res);
217         break;
218     default :
219         RK610_ERR(&client->dev,"RK610 not support dual display at hdmi resolution=%d \n",screen->hdmi_resolution); 
220         return -1;
221         break;
222     }
223     return 0;
224 }
225 static int rk610_scaler_output_timing_config(struct i2c_client *client,struct rk_screen *screen)
226 {
227     char c;
228     int h_st = screen->s_hsync_st;
229     int hs_end = screen->s_hsync_len;
230     int h_act_st = hs_end + screen->s_left_margin;
231     int xres = screen->x_res;
232     int h_act_end = h_act_st + xres;
233     int h_total = h_act_end + screen->s_right_margin;
234     int v_st = screen->s_vsync_st;
235     int vs_end = screen->s_vsync_len;
236     int v_act_st = vs_end + screen->s_upper_margin;
237     int yres = screen->y_res;    
238     int v_act_end = v_act_st + yres;
239     int v_total = v_act_end + screen->s_lower_margin;
240
241     /*      SCL display Frame start point   */
242     c = SCL_DSP_HST_LSB(h_st);
243         rk610_scaler_write_p0_reg(client, SCL_CON5, &c);
244     c = SCL_DSP_HST_MSB(h_st);
245         rk610_scaler_write_p0_reg(client, SCL_CON6, &c);
246
247     c = SCL_DSP_VST_LSB(v_st);
248         rk610_scaler_write_p0_reg(client, SCL_CON7, &c);
249     c = SCL_DSP_VST_MSB(v_st);
250         rk610_scaler_write_p0_reg(client, SCL_CON8, &c);
251     /*      SCL output timing       */
252
253     c = SCL_DSP_HTOTAL_LSB(h_total);
254         rk610_scaler_write_p0_reg(client, SCL_CON9, &c);
255     c = SCL_DSP_HTOTAL_MSB(h_total);
256         rk610_scaler_write_p0_reg(client, SCL_CON10, &c);
257
258     c = SCL_DSP_HS_END(hs_end);
259         rk610_scaler_write_p0_reg(client, SCL_CON11, &c);
260
261     c = SCL_DSP_HACT_ST_LSB(h_act_st);
262         rk610_scaler_write_p0_reg(client, SCL_CON12, &c);
263     c = SCL_DSP_HACT_ST_MSB(h_act_st);
264         rk610_scaler_write_p0_reg(client, SCL_CON13, &c);
265
266     c = SCL_DSP_HACT_END_LSB(h_act_end);
267         rk610_scaler_write_p0_reg(client, SCL_CON14, &c);
268     c = SCL_DSP_HACT_END_MSB(h_act_end);
269         rk610_scaler_write_p0_reg(client, SCL_CON15, &c);
270
271     c = SCL_DSP_VTOTAL_LSB(v_total);
272         rk610_scaler_write_p0_reg(client, SCL_CON16, &c);
273     c = SCL_DSP_VTOTAL_MSB(v_total);
274         rk610_scaler_write_p0_reg(client, SCL_CON17, &c);
275
276     c = SCL_DSP_VS_END(vs_end);
277         rk610_scaler_write_p0_reg(client, SCL_CON18, &c);
278
279     c = SCL_DSP_VACT_ST(v_act_st);
280         rk610_scaler_write_p0_reg(client, SCL_CON19, &c);
281
282     c = SCL_DSP_VACT_END_LSB(v_act_end);
283         rk610_scaler_write_p0_reg(client, SCL_CON20, &c);
284     c = SCL_DSP_VACT_END_MSB(v_act_end); 
285         rk610_scaler_write_p0_reg(client, SCL_CON21, &c);
286  
287     c = SCL_H_BORD_ST_LSB(h_act_st);
288         rk610_scaler_write_p0_reg(client, SCL_CON22, &c);
289     c = SCL_H_BORD_ST_MSB(h_act_st);
290         rk610_scaler_write_p0_reg(client, SCL_CON23, &c);
291
292     c = SCL_H_BORD_END_LSB(h_act_end);
293         rk610_scaler_write_p0_reg(client, SCL_CON24, &c);
294     c = SCL_H_BORD_END_MSB(h_act_end);
295         rk610_scaler_write_p0_reg(client, SCL_CON25, &c);
296
297     c = SCL_V_BORD_ST(v_act_st);
298         rk610_scaler_write_p0_reg(client, SCL_CON26, &c);
299
300     c = SCL_V_BORD_END_LSB(v_act_end);
301         rk610_scaler_write_p0_reg(client, SCL_CON27, &c);
302     c = SCL_V_BORD_END_MSB(v_act_end);
303         rk610_scaler_write_p0_reg(client, SCL_CON28, &c);
304         
305         return 0;
306 }
307 static int rk610_scaler_chg(struct i2c_client *client ,struct rk_screen *screen)
308 {
309
310     RK610_DBG(&client->dev,"%s screen->hdmi_resolution=%d\n",__FUNCTION__,screen->hdmi_resolution);
311     rk610_scaler_fator_config(client,screen);
312     rk610_scaler_enable(client);
313     rk610_scaler_output_timing_config(client,screen); 
314     
315     return 0;
316
317 }
318 #endif
319 static int rk610_lcd_scaler_bypass(struct i2c_client *client,bool enable)//enable:0 bypass 1: scale
320 {
321     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
322     
323     rk610_scaler_disable(client);       
324     rk610_scaler_pll_disable(client);
325     
326     return 0;
327 }
328
329 #ifdef CONFIG_HAS_EARLYSUSPEND
330 static void rk610_lcd_early_suspend(struct early_suspend *h)
331 {
332     struct i2c_client *client = g_lcd_inf->client;
333     char c;
334     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
335     if(g_lcd_inf->screen != NULL){
336         rk610_output_config(client,g_lcd_inf->screen,LCD_OUT_DISABLE);
337     }
338
339     if(ENABLE == g_lcd_inf->scl_inf.scl_pwr){
340         c= SCL_BYPASS(1) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(DISABLE); 
341         rk610_scaler_write_p0_reg(client, SCL_CON0, &c);
342     }
343     if(ENABLE == g_lcd_inf->scl_inf.pll_pwr ){
344         c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);
345             rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);
346     }
347 }
348
349 static void rk610_lcd_early_resume(struct early_suspend *h)
350 {
351     struct i2c_client *client = g_lcd_inf->client;
352     char c;
353     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
354
355     if(g_lcd_inf->screen != NULL){
356         rk610_output_config(client,g_lcd_inf->screen,g_lcd_inf->disp_mode);
357     }
358     if(ENABLE == g_lcd_inf->scl_inf.scl_pwr){
359         c= SCL_BYPASS(0) |SCL_DEN_INV(0) |SCL_H_V_SYNC_INV(0) |SCL_OUT_CLK_INV(0) |SCL_ENABLE(ENABLE);  
360             rk610_scaler_write_p0_reg(client, SCL_CON0, &c);
361     }
362     if(ENABLE == g_lcd_inf->scl_inf.pll_pwr ){
363         c = S_PLL_PWR(1) |S_PLL_RESET(0) |S_PLL_BYPASS(1);
364             rk610_scaler_write_p0_reg(client, S_PLL_CON2, &c);
365     }
366 }
367 #endif
368 int rk610_lcd_scaler_set_param(struct rk_screen *screen,bool enable )//enable:0 bypass 1: scale
369 {
370     int ret=0;
371     struct i2c_client *client = g_lcd_inf->client;
372     if(client == NULL){
373         printk("%s client == NULL FAIL\n",__FUNCTION__);
374         return -1;
375     }
376     if(screen == NULL){
377         printk("%s screen == NULL FAIL\n",__FUNCTION__);
378         return -1;
379     }
380     RK610_DBG(&client->dev,"%s \n",__FUNCTION__);
381     
382     g_lcd_inf->screen = screen;
383     
384 #if defined(CONFIG_HDMI_DUAL_DISP) || defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
385     if(enable == 1){
386         g_lcd_inf->disp_mode = LCD_OUT_SCL;
387         rk610_output_config(client,screen,LCD_OUT_SCL);
388         ret = rk610_scaler_chg(client,screen);
389         }
390         else 
391 #endif
392         {
393             g_lcd_inf->disp_mode = LCD_OUT_BYPASS;
394             rk610_output_config(client,screen,LCD_OUT_BYPASS);
395             ret = rk610_lcd_scaler_bypass(client,enable);
396         }
397         return ret;
398 }
399 int rk610_lcd_init(struct rk610_core_info *rk610_core_info)
400 {
401     if(rk610_core_info->client == NULL){
402         printk("%s client == NULL FAIL\n",__FUNCTION__);
403         return -1;
404     }
405     RK610_DBG(&rk610_core_info->client->dev,"%s \n",__FUNCTION__);
406
407     g_lcd_inf = kmalloc(sizeof(struct rk610_lcd_info), GFP_KERNEL);
408     if(!g_lcd_inf)
409     {
410         dev_err(&rk610_core_info->client->dev, ">> rk610 inf kmalloc fail!");
411         return -ENOMEM;
412     }
413     memset(g_lcd_inf, 0, sizeof(struct rk610_lcd_info));
414
415     g_lcd_inf->client= rk610_core_info->client;
416     
417     rk610_core_info->lcd_pdata = (void *)g_lcd_inf;
418 #ifdef CONFIG_HAS_EARLYSUSPEND
419         g_lcd_inf->early_suspend.suspend = rk610_lcd_early_suspend;
420         g_lcd_inf->early_suspend.resume = rk610_lcd_early_resume;
421         g_lcd_inf->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB- 1;
422         register_early_suspend(&g_lcd_inf->early_suspend);
423 #endif
424     g_lcd_inf->scl_inf.pll_pwr = DISABLE;
425     g_lcd_inf->scl_inf.scl_pwr = DISABLE;
426     g_lcd_inf->disp_mode = LCD_OUT_BYPASS;
427     return 0;
428 }
429
430 static int rk610_lcd_probe(struct platform_device *pdev)
431 {
432         struct rk610_core_info *core_info = NULL;
433         rk_screen *screen = NULL;
434
435         core_info = dev_get_drvdata(pdev->dev.parent);
436         if(!core_info)
437         {
438                 dev_err(&pdev->dev,"rk610 core info is null\n");
439                 return -ENODEV;
440         }
441         screen = rk_fb_get_prmry_screen();
442         if(!screen)
443         {
444                 dev_err(&pdev->dev,"the fb prmry screen is null!\n");
445                 return -ENODEV;
446         }
447         
448 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
449         screen->sscreen_set = rk610_lcd_scaler_set_param;
450 #endif
451         rk610_lcd_init(core_info);
452         rk610_lcd_scaler_set_param(screen,0);
453
454         return 0;
455         
456 }
457 static int rk610_lcd_remove(struct platform_device *pdev)
458 {
459         
460         return 0;
461 }
462
463 static void rk610_lcd_shutdown(struct platform_device *pdev)
464 {
465         
466         return;
467 }
468
469 static struct platform_driver rk610_lcd_driver = {
470         .driver         = {
471                 .name   = "rk610-lcd",
472                 .owner  = THIS_MODULE,
473         },
474         .probe          = rk610_lcd_probe,
475         .remove         = rk610_lcd_remove,
476         .shutdown       = rk610_lcd_shutdown,
477 };
478
479 static int __init rk610_lcd_module_init(void)
480 {
481         return platform_driver_register(&rk610_lcd_driver);
482 }
483 fs_initcall(rk610_lcd_module_init);
484 static void __exit rk610_lcd_exit(void)
485 {
486         platform_driver_unregister(&rk610_lcd_driver);
487 }
488 module_exit(rk610_lcd_exit);
489