]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/video/via/vt1636.c
viafb: rework the I2C support in the VIA framebuffer driver
[mv-sheeva.git] / drivers / video / via / vt1636.c
1 /*
2  * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public
7  * License as published by the Free Software Foundation;
8  * either version 2, or (at your option) any later version.
9
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12  * the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE.See the GNU General Public License
14  * for more details.
15
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc.,
19  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include "global.h"
23
24 u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
25         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
26         u8 index)
27 {
28         u8 data;
29
30         viafb_i2c_readbyte(plvds_chip_info->i2c_port,
31                            plvds_chip_info->lvds_chip_slave_addr, index, &data);
32         return data;
33 }
34
35 void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
36                               *plvds_setting_info, struct lvds_chip_information
37                               *plvds_chip_info, struct IODATA io_data)
38 {
39         int index, data;
40
41         index = io_data.Index;
42         data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
43                 index);
44         data = (data & (~io_data.Mask)) | io_data.Data;
45
46         viafb_i2c_writebyte(plvds_chip_info->i2c_port,
47                             plvds_chip_info->lvds_chip_slave_addr, index, data);
48 }
49
50 void viafb_init_lvds_vt1636(struct lvds_setting_information
51         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
52 {
53         int reg_num, i;
54
55         /* Common settings: */
56         reg_num = ARRAY_SIZE(COMMON_INIT_TBL_VT1636);
57
58         for (i = 0; i < reg_num; i++) {
59                 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
60                                          plvds_chip_info,
61                                          COMMON_INIT_TBL_VT1636[i]);
62         }
63
64         /* Input Data Mode Select */
65         if (plvds_setting_info->device_lcd_dualedge) {
66                 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
67                                          plvds_chip_info,
68                                          DUAL_CHANNEL_ENABLE_TBL_VT1636[0]);
69         } else {
70                 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
71                                          plvds_chip_info,
72                                          SINGLE_CHANNEL_ENABLE_TBL_VT1636[0]);
73         }
74
75         if (plvds_setting_info->LCDDithering) {
76                 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
77                                          plvds_chip_info,
78                                          DITHERING_ENABLE_TBL_VT1636[0]);
79         } else {
80                 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
81                                          plvds_chip_info,
82                                          DITHERING_DISABLE_TBL_VT1636[0]);
83         }
84 }
85
86 void viafb_enable_lvds_vt1636(struct lvds_setting_information
87                         *plvds_setting_info,
88                         struct lvds_chip_information *plvds_chip_info)
89 {
90
91         viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
92                                  VDD_ON_TBL_VT1636[0]);
93
94         /* Pad on: */
95         switch (plvds_chip_info->output_interface) {
96         case INTERFACE_DVP0:
97                 {
98                         viafb_write_reg_mask(SR1E, VIASR, 0xC0, 0xC0);
99                         break;
100                 }
101
102         case INTERFACE_DVP1:
103                 {
104                         viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
105                         break;
106                 }
107
108         case INTERFACE_DFP_LOW:
109                 {
110                         viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x03);
111                         break;
112                 }
113
114         case INTERFACE_DFP_HIGH:
115                 {
116                         viafb_write_reg_mask(SR2A, VIASR, 0x03, 0x0C);
117                         break;
118                 }
119
120         }
121 }
122
123 void viafb_disable_lvds_vt1636(struct lvds_setting_information
124                          *plvds_setting_info,
125                          struct lvds_chip_information *plvds_chip_info)
126 {
127
128         viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
129                                  VDD_OFF_TBL_VT1636[0]);
130
131         /* Pad off: */
132         switch (plvds_chip_info->output_interface) {
133         case INTERFACE_DVP0:
134                 {
135                         viafb_write_reg_mask(SR1E, VIASR, 0x00, 0xC0);
136                         break;
137                 }
138
139         case INTERFACE_DVP1:
140                 {
141                         viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
142                         break;
143                 }
144
145         case INTERFACE_DFP_LOW:
146                 {
147                         viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x03);
148                         break;
149                 }
150
151         case INTERFACE_DFP_HIGH:
152                 {
153                         viafb_write_reg_mask(SR2A, VIASR, 0x00, 0x0C);
154                         break;
155                 }
156
157         }
158 }
159
160 bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
161 {
162         u8 Buffer[2];
163
164         DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
165
166         /* Sense VT1636 LVDS Transmiter */
167         viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
168         VT1636_LVDS_I2C_ADDR;
169
170         /* Check vendor ID first: */
171         viafb_i2c_readbyte(i2c_adapter,
172                            (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
173                            0x00, &Buffer[0]);
174         viafb_i2c_readbyte(i2c_adapter,
175                            (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
176                            0x01, &Buffer[1]);
177
178         if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
179                 return false;
180
181         /* Check Chip ID: */
182         viafb_i2c_readbyte(i2c_adapter,
183                            (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
184                            0x02, &Buffer[0]);
185         viafb_i2c_readbyte(i2c_adapter,
186                            (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
187                            0x03, &Buffer[1]);
188         if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
189                 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
190                         VT1636_LVDS;
191                 return true;
192         }
193
194         return false;
195 }
196
197 static int get_clk_range_index(u32 Clk)
198 {
199         if (Clk < DPA_CLK_30M)
200                 return DPA_CLK_RANGE_30M;
201         else if (Clk < DPA_CLK_50M)
202                 return DPA_CLK_RANGE_30_50M;
203         else if (Clk < DPA_CLK_70M)
204                 return DPA_CLK_RANGE_50_70M;
205         else if (Clk < DPA_CLK_100M)
206                 return DPA_CLK_RANGE_70_100M;
207         else if (Clk < DPA_CLK_150M)
208                 return DPA_CLK_RANGE_100_150M;
209         else
210                 return DPA_CLK_RANGE_150M;
211 }
212
213 static int get_lvds_dpa_setting_index(int panel_size_id,
214                              struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
215                                int tbl_size)
216 {
217         int i;
218
219         for (i = 0; i < tbl_size; i++) {
220                 if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
221                         return i;
222
223                 p_vt1636_dpasetting_tbl++;
224         }
225
226         return 0;
227 }
228
229 static void set_dpa_vt1636(struct lvds_setting_information
230         *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
231                     struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
232 {
233         struct IODATA io_data;
234
235         io_data.Index = 0x09;
236         io_data.Mask = 0x1F;
237         io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
238         viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
239                 plvds_chip_info, io_data);
240
241         io_data.Index = 0x08;
242         io_data.Mask = 0x0F;
243         io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
244         viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
245                 io_data);
246 }
247
248 void viafb_vt1636_patch_skew_on_vt3324(
249         struct lvds_setting_information *plvds_setting_info,
250         struct lvds_chip_information *plvds_chip_info)
251 {
252         int index, size;
253
254         DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
255
256         /* Graphics DPA settings: */
257         index = get_clk_range_index(plvds_setting_info->vclk);
258         viafb_set_dpa_gfx(plvds_chip_info->output_interface,
259                     &GFX_DPA_SETTING_TBL_VT3324[index]);
260
261         /* LVDS Transmitter DPA settings: */
262         size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324);
263         index =
264             get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
265                                        VT1636_DPA_SETTING_TBL_VT3324, size);
266         set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
267                        &VT1636_DPA_SETTING_TBL_VT3324[index]);
268 }
269
270 void viafb_vt1636_patch_skew_on_vt3327(
271         struct lvds_setting_information *plvds_setting_info,
272         struct lvds_chip_information *plvds_chip_info)
273 {
274         int index, size;
275
276         DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
277
278         /* Graphics DPA settings: */
279         index = get_clk_range_index(plvds_setting_info->vclk);
280         viafb_set_dpa_gfx(plvds_chip_info->output_interface,
281                     &GFX_DPA_SETTING_TBL_VT3327[index]);
282
283         /* LVDS Transmitter DPA settings: */
284         size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327);
285         index =
286             get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
287                                        VT1636_DPA_SETTING_TBL_VT3327, size);
288         set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
289                        &VT1636_DPA_SETTING_TBL_VT3327[index]);
290 }
291
292 void viafb_vt1636_patch_skew_on_vt3364(
293         struct lvds_setting_information *plvds_setting_info,
294         struct lvds_chip_information *plvds_chip_info)
295 {
296         int index;
297
298         DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
299
300         /* Graphics DPA settings: */
301         index = get_clk_range_index(plvds_setting_info->vclk);
302         viafb_set_dpa_gfx(plvds_chip_info->output_interface,
303                     &GFX_DPA_SETTING_TBL_VT3364[index]);
304 }