83a6cec9766552c1fcc36eff1a219fee1e2b1092
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / tve / rk610_tv.c
1 /*
2  * rk610_tv.c 
3  *
4  * Driver for rockchip rk610 tv control
5  *  Copyright (C) 2009 
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation;  either version 2 of the  License, or (at your
10  *  option) any later version.
11  *
12  *
13  */
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <linux/i2c.h>
17 #include <linux/delay.h>
18 #include <linux/fcntl.h>
19 #include <linux/fs.h>
20 #include <linux/fb.h>
21 #include <linux/console.h>
22 #include <asm/uaccess.h>
23 #include "rk610_tv.h"
24 #include "../../rk29_fb.h"
25
26 #define DRV_NAME "rk610_tvout"
27 #define RK610_I2C_RATE     100*1000
28
29 volatile int rk610_tv_output_status = RK610_TVOUT_DEAULT;
30 static struct i2c_client *rk610_tv_i2c_client = NULL;
31
32 int rk610_tv_wirte_reg(u8 reg, u8 data)
33 {
34     int ret;
35         if(rk610_tv_i2c_client == NULL)
36                 return -1;
37     ret = i2c_master_reg8_send(rk610_tv_i2c_client, reg, &data, 1, RK610_I2C_RATE);
38         if (ret > 0)
39                 ret = 0;
40         return ret;
41 }
42
43 int rk610_switch_fb(const struct fb_videomode *modedb, int tv_mode)
44 {       
45         struct rk_screen *screen;
46         
47         if(modedb == NULL)
48                 return -1;
49         screen =  kzalloc(sizeof(struct rk_screen), GFP_KERNEL);
50         if(screen == NULL)
51                 return -1;
52         
53         memset(screen, 0, sizeof(struct rk_screen));    
54         /* screen type & face */
55     screen->type = SCREEN_HDMI;
56         screen->mode = modedb->vmode;
57         screen->face = modedb->flag;
58         /* Screen size */
59         screen->x_res = modedb->xres;
60     screen->y_res = modedb->yres;
61
62     /* Timing */
63     screen->pixclock = modedb->pixclock;
64
65         screen->lcdc_aclk = 500000000;
66         screen->left_margin = modedb->left_margin;
67         screen->right_margin = modedb->right_margin;
68         screen->hsync_len = modedb->hsync_len;
69         screen->upper_margin = modedb->upper_margin;
70         screen->lower_margin = modedb->lower_margin;
71         screen->vsync_len = modedb->vsync_len;
72
73         /* Pin polarity */
74         if(FB_SYNC_HOR_HIGH_ACT & modedb->sync)
75                 screen->pin_hsync = 1;
76         else
77                 screen->pin_hsync = 0;
78         if(FB_SYNC_VERT_HIGH_ACT & modedb->sync)
79                 screen->pin_vsync = 1;
80         else
81                 screen->pin_vsync = 0;  
82         screen->pin_den = 0;
83         screen->pin_dclk = 0;
84
85         /* Swap rule */
86     screen->swap_rb = 0;
87     screen->swap_rg = 0;
88     screen->swap_gb = 0;
89     screen->swap_delta = 0;
90     screen->swap_dumy = 0;
91
92     /* Operation function*/
93     screen->init = NULL;
94     screen->standby = NULL;     
95     
96     switch(tv_mode)
97         {
98 #ifdef CONFIG_RK610_TVOUT_CVBS
99                 case TVOUT_CVBS_NTSC:
100                 case TVOUT_CVBS_PAL:
101             screen->init = rk610_tv_cvbs_init;;
102                 break;
103 #endif
104
105 #ifdef CONFIG_RK610_TVOUT_YPbPr
106                 case TVOUT_YPbPr_720x480p_60:
107                 case TVOUT_YPbPr_720x576p_50:
108                 case TVOUT_YPbPr_1280x720p_50:
109                 case TVOUT_YPbPr_1280x720p_60:
110                 //case TVOUT_YPbPr_1920x1080i_50:
111                 case TVOUT_YPbPr_1920x1080i_60:
112                 case TVOUT_YPbPr_1920x1080p_50:
113                 case TVOUT_YPbPr_1920x1080p_60:
114                         screen->init = rk610_tv_ypbpr_init;
115                         break;
116 #endif
117                 default:{
118                         kfree(screen);
119                         return -1;
120                 }
121                 break;
122         }
123         rk610_tv_output_status = tv_mode;
124         FB_Switch_Screen(screen, 1);
125         kfree(screen);
126         return 0;
127 }
128
129 int rk610_tv_standby(int type)
130 {
131         int ret;
132
133         switch(type)
134         {
135                 #ifdef CONFIG_RK610_TVOUT_CVBS
136                 case RK610_TVOUT_CVBS:
137                         if(rk610_cvbs_monspecs.enable == 0)
138                                 return 0;
139                         #ifdef CONFIG_RK610_TVOUT_YPbPr
140                         if(rk610_ypbpr_monspecs.enable == 1)
141                                 return 0;
142                         #endif
143                         break;
144                 #endif
145                 #ifdef CONFIG_RK610_TVOUT_YPbPr
146                 case RK610_TVOUT_YPBPR:
147                         if(rk610_ypbpr_monspecs.enable == 0)
148                                 return 0;
149                         #ifdef CONFIG_RK610_TVOUT_CVBS
150                         if(rk610_cvbs_monspecs.enable == 1)
151                                 return 0;
152                         #endif
153                         break;
154                 #endif
155                 default:
156                         break;
157         }
158
159         ret = rk610_tv_wirte_reg(TVE_POWERCR, 0);
160         if(ret < 0){
161                 printk("[%s] rk610_tv_wirte_reg err!\n", __FUNCTION__);
162                 return ret;
163         }
164         
165         ret = rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, 0);
166         if(ret < 0){
167                 printk("[%s] rk610_control_send_byte err!\n", __FUNCTION__);
168                 return ret;
169         }
170         return 0;
171 }
172
173 static int rk610_tv_probe(struct i2c_client *client,const struct i2c_device_id *id)
174 {
175         int rc = 0;
176         
177         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
178                 rc = -ENODEV;
179                 goto failout;
180         }
181         rk610_tv_i2c_client = client;
182
183 #ifdef CONFIG_RK610_TVOUT_YPbPr
184         rk610_register_display_ypbpr(&client->dev);
185         if(rk610_tv_output_status > TVOUT_CVBS_PAL)
186                 rk_display_device_enable(rk610_ypbpr_monspecs.ddev);
187 #endif
188
189 #ifdef CONFIG_RK610_TVOUT_CVBS
190         rk610_register_display_cvbs(&client->dev);
191         if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
192                 rk_display_device_enable(rk610_cvbs_monspecs.ddev);
193 #endif
194         
195     printk(KERN_INFO "rk610_tv ver 1.0 probe ok\n");
196     return 0;
197 failout:
198         kfree(client);
199         return rc;
200 }
201
202 static int rk610_tv_remove(struct i2c_client *client)
203 {
204         return 0;
205 }
206
207
208 static const struct i2c_device_id rk610_tv_id[] = {
209         { DRV_NAME, 0 },
210         { }
211 };
212 MODULE_DEVICE_TABLE(i2c, rk610_tv_id);
213
214 static struct i2c_driver rk610_tv_driver = {
215         .driver         = {
216                 .name   = DRV_NAME,
217         },
218         .id_table = rk610_tv_id,
219         .probe = rk610_tv_probe,
220         .remove = rk610_tv_remove,
221 };
222
223 static int __init rk610_tv_init(void)
224 {
225         int ret = 0;
226         ret = i2c_add_driver(&rk610_tv_driver);
227         if(ret < 0){
228                 printk("i2c_add_driver err, ret = %d\n", ret);
229         }
230         return ret;
231 }
232
233 static void __exit rk610_tv_exit(void)
234 {
235     i2c_del_driver(&rk610_tv_driver);
236 }
237
238 module_init(rk610_tv_init);
239 //late_initcall(rk610_tv_init);
240 module_exit(rk610_tv_exit);
241
242 /* Module information */
243 MODULE_DESCRIPTION("ROCKCHIP RK610 TV Output");
244 MODULE_LICENSE("GPL");
245
246