rk3036: add tv encoder code.
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / tve / rk610 / rk610_tv_cvbs.c
1 #include <linux/ctype.h>
2 #include <linux/string.h>
3 #include <linux/display-sys.h>
4 #include "rk610_tv.h"
5
6
7 #ifdef CONFIG_DISPLAY_KEY_LED_CONTROL
8 #define RK610_LED_CVBS_PIN      RK29_PIN4_PD3
9 #else
10 #define RK610_LED_CVBS_PIN      INVALID_GPIO
11 #endif
12
13 #ifdef USE_RGB2CCIR
14 static const struct fb_videomode rk610_cvbs_mode [] = {
15                 //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
16         {       "NTSC",                         60,                     720,    480,    27000000,       116,    16,             25,             14,             6,              6,              0,                      1,              OUT_P888        },
17         {       "PAL",                          50,                     720,    576,    27000000,       126,    12,             37,             6,              6,              6,              0,                      1,              OUT_P888        },
18 };
19 #else
20 static const struct fb_videomode rk610_cvbs_mode [] = {
21                 //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag
22         {       "NTSC",                         60,                     720,    480,    27000000,       116,    16,             16,             3,              6,              3,              0,                      1,              OUT_CCIR656     },
23         {       "PAL",                          50,                     720,    576,    27000000,       126,    12,             19,             2,              6,              3,              0,                      1,              OUT_CCIR656     },
24 };
25 #endif
26
27 struct rk610_monspecs rk610_cvbs_monspecs;
28
29
30 int rk610_tv_cvbs_init(void)
31 {
32         unsigned char TVE_Regs[9];
33         unsigned char TVE_CON_Reg;
34         int ret, i;
35         
36         rk610_tv_wirte_reg(TVE_HDTVCR, TVE_RESET);
37
38         memset(TVE_Regs, 0, 9);
39         TVE_CON_Reg = TVE_CONTROL_CVBS_3_CHANNEL_ENALBE;
40         TVE_Regs[TVE_VINCR]     =       TVE_VINCR_PIX_DATA_DELAY(0) | TVE_VINCR_H_SYNC_POLARITY_NEGTIVE | TVE_VINCR_V_SYNC_POLARITY_NEGTIVE | TVE_VINCR_VSYNC_FUNCTION_VSYNC;
41         TVE_Regs[TVE_POWERCR]   =       TVE_DAC_Y_ENABLE | TVE_DAC_U_ENABLE | TVE_DAC_V_ENABLE;
42         TVE_Regs[TVE_VOUTCR]    =       TVE_VOUTCR_OUTPUT_CVBS;
43         TVE_Regs[TVE_YADJCR]    =       0x17;
44         TVE_Regs[TVE_YCBADJCR]  =       0x10;
45         TVE_Regs[TVE_YCRADJCR]  =       0x10;
46         
47         switch(rk610_tv_output_status) {
48                 case TVOUT_CVBS_NTSC:
49                         TVE_Regs[TVE_VFCR]              = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_7_5_IRE | TVE_VFCR_NTSC;
50                         #ifdef USE_RGB2CCIR
51                         TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
52                         TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
53                         TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_NTSC | RGB2CCIR_ENABLE;
54                         #else
55                         TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
56                         TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
57                         #endif                  
58                         break;
59                 case TVOUT_CVBS_PAL:
60                         TVE_Regs[TVE_VFCR]              = TVE_VFCR_ENABLE_SUBCARRIER_RESET | TVE_VFCR_VIN_RANGE_16_235 | TVE_VFCR_BLACK_0_IRE | TVE_VFCR_PAL_B_N;               
61                         #ifdef USE_RGB2CCIR
62                         TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT601_SLAVE);
63                         TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_COLOR_CONVERT_REC601 | TVE_INPUT_DATA_RGB | TVE_OUTPUT_MODE_PAL_NTSC;
64                         TVE_CON_Reg |= RGB2CCIR_INPUT_DATA_FORMAT(0) | RGB2CCIR_RGB_SWAP_DISABLE | RGB2CCIR_INPUT_PROGRESSIVE | RGB2CCIR_CVBS_PAL | RGB2CCIR_ENABLE;
65                         #else
66                         TVE_Regs[TVE_VINCR]             |=      TVE_VINCR_INPUT_FORMAT(INPUT_FORMAT_BT656);
67                         TVE_Regs[TVE_HDTVCR]    =       TVE_FILTER(0) | TVE_INPUT_DATA_YUV | TVE_OUTPUT_MODE_PAL_NTSC;
68                         #endif                  
69                         break;
70                 default:
71                         return -1;
72         }
73         
74         for(i = 0; i < sizeof(TVE_Regs); i++){
75 //              printk(KERN_ERR "reg[%d] = 0x%02x\n", i, TVE_Regs[i]);
76                 ret = rk610_tv_wirte_reg(i, TVE_Regs[i]);
77                 if(ret < 0){
78                         printk(KERN_ERR "rk610_tv_wirte_reg %d err!\n", i);
79                         return ret;
80                 }
81         }
82 //      printk(KERN_ERR "TVE_CON_Reg = 0x%02x\n", TVE_CON_Reg);
83         rk610_control_send_byte(RK610_CONTROL_REG_TVE_CON, TVE_CON_Reg);
84         #ifdef USE_RGB2CCIR
85         rk610_control_send_byte(RK610_CONTROL_REG_CCIR_RESET, 0x01);
86         #endif
87         return 0;
88 }
89
90 static int rk610_cvbs_set_enable(struct rk_display_device *device, int enable)
91 {
92         if(rk610_cvbs_monspecs.enable != enable || rk610_cvbs_monspecs.mode_set != rk610_tv_output_status)
93         {
94                 if(enable == 0)
95                 {
96                         rk610_tv_standby(RK610_TVOUT_CVBS);
97                         rk610_cvbs_monspecs.enable = 0;
98                         if(RK610_LED_CVBS_PIN != INVALID_GPIO)
99                                 gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
100                 }
101                 else if(enable == 1)
102                 {
103                         rk610_switch_fb(rk610_cvbs_monspecs.mode, rk610_cvbs_monspecs.mode_set);
104                         rk610_cvbs_monspecs.enable = 1;
105                         if(RK610_LED_CVBS_PIN != INVALID_GPIO)
106                                 gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_LOW);
107                 }
108         }
109         return 0;
110 }
111
112 static int rk610_cvbs_get_enable(struct rk_display_device *device)
113 {
114         return rk610_cvbs_monspecs.enable;
115 }
116
117 static int rk610_cvbs_get_status(struct rk_display_device *device)
118 {
119         if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60)
120                 return 1;
121         else
122                 return 0;
123 }
124
125 static int rk610_cvbs_get_modelist(struct rk_display_device *device, struct list_head **modelist)
126 {
127         *modelist = &(rk610_cvbs_monspecs.modelist);
128         return 0;
129 }
130
131 static int rk610_cvbs_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
132 {
133         int i;
134
135         for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
136         {
137                 if(fb_mode_is_equal(&rk610_cvbs_mode[i], mode))
138                 {       
139                         if( ((i + 1) != rk610_tv_output_status) )
140                         {
141                                 rk610_cvbs_monspecs.mode_set = i + 1;
142                                 rk610_cvbs_monspecs.mode = (struct fb_videomode *)&rk610_cvbs_mode[i];
143                         }
144                         return 0;
145                 }
146         }
147         
148         return -1;
149 }
150
151 static int rk610_cvbs_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
152 {
153         *mode = *(rk610_cvbs_monspecs.mode);
154         return 0;
155 }
156
157 static struct rk_display_ops rk610_cvbs_display_ops = {
158         .setenable = rk610_cvbs_set_enable,
159         .getenable = rk610_cvbs_get_enable,
160         .getstatus = rk610_cvbs_get_status,
161         .getmodelist = rk610_cvbs_get_modelist,
162         .setmode = rk610_cvbs_set_mode,
163         .getmode = rk610_cvbs_get_mode,
164 };
165
166 static int rk610_display_cvbs_probe(struct rk_display_device *device, void *devdata)
167 {
168         device->owner = THIS_MODULE;
169         strcpy(device->type, "TV");
170         device->priority = DISPLAY_PRIORITY_TV;
171         device->priv_data = devdata;
172         device->ops = &rk610_cvbs_display_ops;
173         return 1;
174 }
175
176 static struct rk_display_driver display_rk610_cvbs = {
177         .probe = rk610_display_cvbs_probe,
178 };
179
180 int rk610_register_display_cvbs(struct device *parent)
181 {
182         int i;
183         
184         memset(&rk610_cvbs_monspecs, 0, sizeof(struct rk610_monspecs));
185         INIT_LIST_HEAD(&rk610_cvbs_monspecs.modelist);
186         for(i = 0; i < ARRAY_SIZE(rk610_cvbs_mode); i++)
187                 fb_add_videomode(&rk610_cvbs_mode[i], &rk610_cvbs_monspecs.modelist);
188         if(rk610_tv_output_status < TVOUT_YPbPr_720x480p_60) {
189                 rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[rk610_tv_output_status - 1]);
190                 rk610_cvbs_monspecs.mode_set = rk610_tv_output_status;
191         }
192         else {
193                 rk610_cvbs_monspecs.mode = (struct fb_videomode *)&(rk610_cvbs_mode[0]);
194                 rk610_cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
195         }
196         rk610_cvbs_monspecs.ddev = rk_display_device_register(&display_rk610_cvbs, parent, NULL);
197         if(RK610_LED_CVBS_PIN != INVALID_GPIO)
198     {        
199         if(gpio_request(RK610_LED_CVBS_PIN, NULL) != 0)
200         {
201             gpio_free(RK610_LED_CVBS_PIN);
202             dev_err(rk610_cvbs_monspecs.ddev->dev, ">>>>>> RK610_LED_CVBS_PIN gpio_request err \n ");
203             return -1;
204         }
205                 gpio_pull_updown(RK610_LED_CVBS_PIN,GPIOPullUp);
206                 gpio_direction_output(RK610_LED_CVBS_PIN, GPIO_HIGH);
207     }
208         return 0;
209 }