1*64b70da0SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2f7018c21STomi Valkeinen /*
3f7018c21STomi Valkeinen * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
4f7018c21STomi Valkeinen * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
5f7018c21STomi Valkeinen
6f7018c21STomi Valkeinen */
7f7018c21STomi Valkeinen
8f7018c21STomi Valkeinen #include <linux/via-core.h>
9f7018c21STomi Valkeinen #include <linux/via_i2c.h>
10f7018c21STomi Valkeinen #include "global.h"
11f7018c21STomi Valkeinen
12f7018c21STomi Valkeinen static const struct IODATA common_init_data[] = {
13f7018c21STomi Valkeinen /* Index, Mask, Value */
14f7018c21STomi Valkeinen /* Set panel power sequence timing */
15f7018c21STomi Valkeinen {0x10, 0xC0, 0x00},
16f7018c21STomi Valkeinen /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
17f7018c21STomi Valkeinen {0x0B, 0xFF, 0x40},
18f7018c21STomi Valkeinen /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
19f7018c21STomi Valkeinen {0x0C, 0xFF, 0x31},
20f7018c21STomi Valkeinen /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
21f7018c21STomi Valkeinen {0x0D, 0xFF, 0x31},
22f7018c21STomi Valkeinen /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
23f7018c21STomi Valkeinen {0x0E, 0xFF, 0x68},
24f7018c21STomi Valkeinen /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
25f7018c21STomi Valkeinen {0x0F, 0xFF, 0x68},
26f7018c21STomi Valkeinen /* LVDS output power up */
27f7018c21STomi Valkeinen {0x09, 0xA0, 0xA0},
28f7018c21STomi Valkeinen /* turn on back light */
29f7018c21STomi Valkeinen {0x10, 0x33, 0x13}
30f7018c21STomi Valkeinen };
31f7018c21STomi Valkeinen
32f7018c21STomi Valkeinen /* Index, Mask, Value */
33f7018c21STomi Valkeinen static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
34f7018c21STomi Valkeinen static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
35f7018c21STomi Valkeinen static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
36f7018c21STomi Valkeinen static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
37f7018c21STomi Valkeinen static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
38f7018c21STomi Valkeinen static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
39f7018c21STomi Valkeinen
viafb_gpio_i2c_read_lvds(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info,u8 index)40f7018c21STomi Valkeinen u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
41f7018c21STomi Valkeinen *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
42f7018c21STomi Valkeinen u8 index)
43f7018c21STomi Valkeinen {
44f7018c21STomi Valkeinen u8 data;
45f7018c21STomi Valkeinen
46f7018c21STomi Valkeinen viafb_i2c_readbyte(plvds_chip_info->i2c_port,
47f7018c21STomi Valkeinen plvds_chip_info->lvds_chip_slave_addr, index, &data);
48f7018c21STomi Valkeinen return data;
49f7018c21STomi Valkeinen }
50f7018c21STomi Valkeinen
viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info,struct IODATA io_data)51f7018c21STomi Valkeinen void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
52f7018c21STomi Valkeinen *plvds_setting_info, struct lvds_chip_information
53f7018c21STomi Valkeinen *plvds_chip_info, struct IODATA io_data)
54f7018c21STomi Valkeinen {
55f7018c21STomi Valkeinen int index, data;
56f7018c21STomi Valkeinen
57f7018c21STomi Valkeinen index = io_data.Index;
58f7018c21STomi Valkeinen data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
59f7018c21STomi Valkeinen index);
60f7018c21STomi Valkeinen data = (data & (~io_data.Mask)) | io_data.Data;
61f7018c21STomi Valkeinen
62f7018c21STomi Valkeinen viafb_i2c_writebyte(plvds_chip_info->i2c_port,
63f7018c21STomi Valkeinen plvds_chip_info->lvds_chip_slave_addr, index, data);
64f7018c21STomi Valkeinen }
65f7018c21STomi Valkeinen
viafb_init_lvds_vt1636(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info)66f7018c21STomi Valkeinen void viafb_init_lvds_vt1636(struct lvds_setting_information
67f7018c21STomi Valkeinen *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
68f7018c21STomi Valkeinen {
69f7018c21STomi Valkeinen int reg_num, i;
70f7018c21STomi Valkeinen
71f7018c21STomi Valkeinen /* Common settings: */
72f7018c21STomi Valkeinen reg_num = ARRAY_SIZE(common_init_data);
73f7018c21STomi Valkeinen for (i = 0; i < reg_num; i++)
74f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
75f7018c21STomi Valkeinen plvds_chip_info, common_init_data[i]);
76f7018c21STomi Valkeinen
77f7018c21STomi Valkeinen /* Input Data Mode Select */
78f7018c21STomi Valkeinen if (plvds_setting_info->device_lcd_dualedge)
79f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
80f7018c21STomi Valkeinen plvds_chip_info, dual_channel_enable_data);
81f7018c21STomi Valkeinen else
82f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
83f7018c21STomi Valkeinen plvds_chip_info, single_channel_enable_data);
84f7018c21STomi Valkeinen
85f7018c21STomi Valkeinen if (plvds_setting_info->LCDDithering)
86f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
87f7018c21STomi Valkeinen plvds_chip_info, dithering_enable_data);
88f7018c21STomi Valkeinen else
89f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
90f7018c21STomi Valkeinen plvds_chip_info, dithering_disable_data);
91f7018c21STomi Valkeinen }
92f7018c21STomi Valkeinen
viafb_enable_lvds_vt1636(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info)93f7018c21STomi Valkeinen void viafb_enable_lvds_vt1636(struct lvds_setting_information
94f7018c21STomi Valkeinen *plvds_setting_info,
95f7018c21STomi Valkeinen struct lvds_chip_information *plvds_chip_info)
96f7018c21STomi Valkeinen {
97f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
98f7018c21STomi Valkeinen vdd_on_data);
99f7018c21STomi Valkeinen }
100f7018c21STomi Valkeinen
viafb_disable_lvds_vt1636(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info)101f7018c21STomi Valkeinen void viafb_disable_lvds_vt1636(struct lvds_setting_information
102f7018c21STomi Valkeinen *plvds_setting_info,
103f7018c21STomi Valkeinen struct lvds_chip_information *plvds_chip_info)
104f7018c21STomi Valkeinen {
105f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
106f7018c21STomi Valkeinen vdd_off_data);
107f7018c21STomi Valkeinen }
108f7018c21STomi Valkeinen
viafb_lvds_identify_vt1636(u8 i2c_adapter)109f7018c21STomi Valkeinen bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
110f7018c21STomi Valkeinen {
111f7018c21STomi Valkeinen u8 Buffer[2];
112f7018c21STomi Valkeinen
113f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
114f7018c21STomi Valkeinen
115f7018c21STomi Valkeinen /* Sense VT1636 LVDS Transmiter */
116f7018c21STomi Valkeinen viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
117f7018c21STomi Valkeinen VT1636_LVDS_I2C_ADDR;
118f7018c21STomi Valkeinen
119f7018c21STomi Valkeinen /* Check vendor ID first: */
120f7018c21STomi Valkeinen if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
121f7018c21STomi Valkeinen 0x00, &Buffer[0]))
122f7018c21STomi Valkeinen return false;
123f7018c21STomi Valkeinen viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
124f7018c21STomi Valkeinen
125f7018c21STomi Valkeinen if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
126f7018c21STomi Valkeinen return false;
127f7018c21STomi Valkeinen
128f7018c21STomi Valkeinen /* Check Chip ID: */
129f7018c21STomi Valkeinen viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
130f7018c21STomi Valkeinen viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
131f7018c21STomi Valkeinen if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
132f7018c21STomi Valkeinen viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
133f7018c21STomi Valkeinen VT1636_LVDS;
134f7018c21STomi Valkeinen return true;
135f7018c21STomi Valkeinen }
136f7018c21STomi Valkeinen
137f7018c21STomi Valkeinen return false;
138f7018c21STomi Valkeinen }
139f7018c21STomi Valkeinen
get_clk_range_index(u32 Clk)140f7018c21STomi Valkeinen static int get_clk_range_index(u32 Clk)
141f7018c21STomi Valkeinen {
142f7018c21STomi Valkeinen if (Clk < DPA_CLK_30M)
143f7018c21STomi Valkeinen return DPA_CLK_RANGE_30M;
144f7018c21STomi Valkeinen else if (Clk < DPA_CLK_50M)
145f7018c21STomi Valkeinen return DPA_CLK_RANGE_30_50M;
146f7018c21STomi Valkeinen else if (Clk < DPA_CLK_70M)
147f7018c21STomi Valkeinen return DPA_CLK_RANGE_50_70M;
148f7018c21STomi Valkeinen else if (Clk < DPA_CLK_100M)
149f7018c21STomi Valkeinen return DPA_CLK_RANGE_70_100M;
150f7018c21STomi Valkeinen else if (Clk < DPA_CLK_150M)
151f7018c21STomi Valkeinen return DPA_CLK_RANGE_100_150M;
152f7018c21STomi Valkeinen else
153f7018c21STomi Valkeinen return DPA_CLK_RANGE_150M;
154f7018c21STomi Valkeinen }
155f7018c21STomi Valkeinen
set_dpa_vt1636(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info,struct VT1636_DPA_SETTING * p_vt1636_dpa_setting)156f7018c21STomi Valkeinen static void set_dpa_vt1636(struct lvds_setting_information
157f7018c21STomi Valkeinen *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
158f7018c21STomi Valkeinen struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
159f7018c21STomi Valkeinen {
160f7018c21STomi Valkeinen struct IODATA io_data;
161f7018c21STomi Valkeinen
162f7018c21STomi Valkeinen io_data.Index = 0x09;
163f7018c21STomi Valkeinen io_data.Mask = 0x1F;
164f7018c21STomi Valkeinen io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
165f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
166f7018c21STomi Valkeinen plvds_chip_info, io_data);
167f7018c21STomi Valkeinen
168f7018c21STomi Valkeinen io_data.Index = 0x08;
169f7018c21STomi Valkeinen io_data.Mask = 0x0F;
170f7018c21STomi Valkeinen io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
171f7018c21STomi Valkeinen viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
172f7018c21STomi Valkeinen io_data);
173f7018c21STomi Valkeinen }
174f7018c21STomi Valkeinen
viafb_vt1636_patch_skew_on_vt3324(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info)175f7018c21STomi Valkeinen void viafb_vt1636_patch_skew_on_vt3324(
176f7018c21STomi Valkeinen struct lvds_setting_information *plvds_setting_info,
177f7018c21STomi Valkeinen struct lvds_chip_information *plvds_chip_info)
178f7018c21STomi Valkeinen {
179f7018c21STomi Valkeinen struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
180f7018c21STomi Valkeinen *pdpa;
181f7018c21STomi Valkeinen int index;
182f7018c21STomi Valkeinen
183f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
184f7018c21STomi Valkeinen
185f7018c21STomi Valkeinen /* Graphics DPA settings: */
186f7018c21STomi Valkeinen index = get_clk_range_index(plvds_setting_info->vclk);
187f7018c21STomi Valkeinen viafb_set_dpa_gfx(plvds_chip_info->output_interface,
188f7018c21STomi Valkeinen &GFX_DPA_SETTING_TBL_VT3324[index]);
189f7018c21STomi Valkeinen
190f7018c21STomi Valkeinen /* LVDS Transmitter DPA settings: */
191f7018c21STomi Valkeinen if (plvds_setting_info->lcd_panel_hres == 1600 &&
192f7018c21STomi Valkeinen plvds_setting_info->lcd_panel_vres == 1200)
193f7018c21STomi Valkeinen pdpa = &dpa_16x12;
194f7018c21STomi Valkeinen else
195f7018c21STomi Valkeinen pdpa = &dpa;
196f7018c21STomi Valkeinen
197f7018c21STomi Valkeinen set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
198f7018c21STomi Valkeinen }
199f7018c21STomi Valkeinen
viafb_vt1636_patch_skew_on_vt3327(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info)200f7018c21STomi Valkeinen void viafb_vt1636_patch_skew_on_vt3327(
201f7018c21STomi Valkeinen struct lvds_setting_information *plvds_setting_info,
202f7018c21STomi Valkeinen struct lvds_chip_information *plvds_chip_info)
203f7018c21STomi Valkeinen {
204f7018c21STomi Valkeinen struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
205f7018c21STomi Valkeinen int index;
206f7018c21STomi Valkeinen
207f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
208f7018c21STomi Valkeinen
209f7018c21STomi Valkeinen /* Graphics DPA settings: */
210f7018c21STomi Valkeinen index = get_clk_range_index(plvds_setting_info->vclk);
211f7018c21STomi Valkeinen viafb_set_dpa_gfx(plvds_chip_info->output_interface,
212f7018c21STomi Valkeinen &GFX_DPA_SETTING_TBL_VT3327[index]);
213f7018c21STomi Valkeinen
214f7018c21STomi Valkeinen /* LVDS Transmitter DPA settings: */
215f7018c21STomi Valkeinen set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
216f7018c21STomi Valkeinen }
217f7018c21STomi Valkeinen
viafb_vt1636_patch_skew_on_vt3364(struct lvds_setting_information * plvds_setting_info,struct lvds_chip_information * plvds_chip_info)218f7018c21STomi Valkeinen void viafb_vt1636_patch_skew_on_vt3364(
219f7018c21STomi Valkeinen struct lvds_setting_information *plvds_setting_info,
220f7018c21STomi Valkeinen struct lvds_chip_information *plvds_chip_info)
221f7018c21STomi Valkeinen {
222f7018c21STomi Valkeinen int index;
223f7018c21STomi Valkeinen
224f7018c21STomi Valkeinen DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
225f7018c21STomi Valkeinen
226f7018c21STomi Valkeinen /* Graphics DPA settings: */
227f7018c21STomi Valkeinen index = get_clk_range_index(plvds_setting_info->vclk);
228f7018c21STomi Valkeinen viafb_set_dpa_gfx(plvds_chip_info->output_interface,
229f7018c21STomi Valkeinen &GFX_DPA_SETTING_TBL_VT3364[index]);
230f7018c21STomi Valkeinen }
231