162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
462306a36Sopenharmony_ci * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/via-core.h>
962306a36Sopenharmony_ci#include <linux/via_i2c.h>
1062306a36Sopenharmony_ci#include "global.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic const struct IODATA common_init_data[] = {
1362306a36Sopenharmony_ci/*  Index, Mask, Value */
1462306a36Sopenharmony_ci	/* Set panel power sequence timing */
1562306a36Sopenharmony_ci	{0x10, 0xC0, 0x00},
1662306a36Sopenharmony_ci	/* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
1762306a36Sopenharmony_ci	{0x0B, 0xFF, 0x40},
1862306a36Sopenharmony_ci	/* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
1962306a36Sopenharmony_ci	{0x0C, 0xFF, 0x31},
2062306a36Sopenharmony_ci	/* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
2162306a36Sopenharmony_ci	{0x0D, 0xFF, 0x31},
2262306a36Sopenharmony_ci	/* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
2362306a36Sopenharmony_ci	{0x0E, 0xFF, 0x68},
2462306a36Sopenharmony_ci	/* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
2562306a36Sopenharmony_ci	{0x0F, 0xFF, 0x68},
2662306a36Sopenharmony_ci	/* LVDS output power up */
2762306a36Sopenharmony_ci	{0x09, 0xA0, 0xA0},
2862306a36Sopenharmony_ci	/* turn on back light */
2962306a36Sopenharmony_ci	{0x10, 0x33, 0x13}
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* Index, Mask, Value */
3362306a36Sopenharmony_cistatic const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
3462306a36Sopenharmony_cistatic const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
3562306a36Sopenharmony_cistatic const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
3662306a36Sopenharmony_cistatic const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
3762306a36Sopenharmony_cistatic const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
3862306a36Sopenharmony_cistatic const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ciu8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
4162306a36Sopenharmony_ci	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
4262306a36Sopenharmony_ci	u8 index)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	u8 data;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	viafb_i2c_readbyte(plvds_chip_info->i2c_port,
4762306a36Sopenharmony_ci			   plvds_chip_info->lvds_chip_slave_addr, index, &data);
4862306a36Sopenharmony_ci	return data;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_civoid viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
5262306a36Sopenharmony_ci			      *plvds_setting_info, struct lvds_chip_information
5362306a36Sopenharmony_ci			      *plvds_chip_info, struct IODATA io_data)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	int index, data;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	index = io_data.Index;
5862306a36Sopenharmony_ci	data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
5962306a36Sopenharmony_ci		index);
6062306a36Sopenharmony_ci	data = (data & (~io_data.Mask)) | io_data.Data;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	viafb_i2c_writebyte(plvds_chip_info->i2c_port,
6362306a36Sopenharmony_ci			    plvds_chip_info->lvds_chip_slave_addr, index, data);
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_civoid viafb_init_lvds_vt1636(struct lvds_setting_information
6762306a36Sopenharmony_ci	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	int reg_num, i;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/* Common settings: */
7262306a36Sopenharmony_ci	reg_num = ARRAY_SIZE(common_init_data);
7362306a36Sopenharmony_ci	for (i = 0; i < reg_num; i++)
7462306a36Sopenharmony_ci		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
7562306a36Sopenharmony_ci			plvds_chip_info, common_init_data[i]);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* Input Data Mode Select */
7862306a36Sopenharmony_ci	if (plvds_setting_info->device_lcd_dualedge)
7962306a36Sopenharmony_ci		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
8062306a36Sopenharmony_ci			plvds_chip_info, dual_channel_enable_data);
8162306a36Sopenharmony_ci	else
8262306a36Sopenharmony_ci		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
8362306a36Sopenharmony_ci			plvds_chip_info, single_channel_enable_data);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (plvds_setting_info->LCDDithering)
8662306a36Sopenharmony_ci		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
8762306a36Sopenharmony_ci			plvds_chip_info, dithering_enable_data);
8862306a36Sopenharmony_ci	else
8962306a36Sopenharmony_ci		viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
9062306a36Sopenharmony_ci			plvds_chip_info, dithering_disable_data);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_civoid viafb_enable_lvds_vt1636(struct lvds_setting_information
9462306a36Sopenharmony_ci			*plvds_setting_info,
9562306a36Sopenharmony_ci			struct lvds_chip_information *plvds_chip_info)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
9862306a36Sopenharmony_ci		vdd_on_data);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_civoid viafb_disable_lvds_vt1636(struct lvds_setting_information
10262306a36Sopenharmony_ci			 *plvds_setting_info,
10362306a36Sopenharmony_ci			 struct lvds_chip_information *plvds_chip_info)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
10662306a36Sopenharmony_ci		vdd_off_data);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cibool viafb_lvds_identify_vt1636(u8 i2c_adapter)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	u8 Buffer[2];
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	/* Sense VT1636 LVDS Transmiter */
11662306a36Sopenharmony_ci	viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
11762306a36Sopenharmony_ci		VT1636_LVDS_I2C_ADDR;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	/* Check vendor ID first: */
12062306a36Sopenharmony_ci	if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
12162306a36Sopenharmony_ci					0x00, &Buffer[0]))
12262306a36Sopenharmony_ci		return false;
12362306a36Sopenharmony_ci	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
12662306a36Sopenharmony_ci		return false;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* Check Chip ID: */
12962306a36Sopenharmony_ci	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
13062306a36Sopenharmony_ci	viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
13162306a36Sopenharmony_ci	if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
13262306a36Sopenharmony_ci		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
13362306a36Sopenharmony_ci			VT1636_LVDS;
13462306a36Sopenharmony_ci		return true;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	return false;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic int get_clk_range_index(u32 Clk)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	if (Clk < DPA_CLK_30M)
14362306a36Sopenharmony_ci		return DPA_CLK_RANGE_30M;
14462306a36Sopenharmony_ci	else if (Clk < DPA_CLK_50M)
14562306a36Sopenharmony_ci		return DPA_CLK_RANGE_30_50M;
14662306a36Sopenharmony_ci	else if (Clk < DPA_CLK_70M)
14762306a36Sopenharmony_ci		return DPA_CLK_RANGE_50_70M;
14862306a36Sopenharmony_ci	else if (Clk < DPA_CLK_100M)
14962306a36Sopenharmony_ci		return DPA_CLK_RANGE_70_100M;
15062306a36Sopenharmony_ci	else if (Clk < DPA_CLK_150M)
15162306a36Sopenharmony_ci		return DPA_CLK_RANGE_100_150M;
15262306a36Sopenharmony_ci	else
15362306a36Sopenharmony_ci		return DPA_CLK_RANGE_150M;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic void set_dpa_vt1636(struct lvds_setting_information
15762306a36Sopenharmony_ci	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
15862306a36Sopenharmony_ci		    struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	struct IODATA io_data;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	io_data.Index = 0x09;
16362306a36Sopenharmony_ci	io_data.Mask = 0x1F;
16462306a36Sopenharmony_ci	io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
16562306a36Sopenharmony_ci	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
16662306a36Sopenharmony_ci		plvds_chip_info, io_data);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	io_data.Index = 0x08;
16962306a36Sopenharmony_ci	io_data.Mask = 0x0F;
17062306a36Sopenharmony_ci	io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
17162306a36Sopenharmony_ci	viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
17262306a36Sopenharmony_ci		io_data);
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_civoid viafb_vt1636_patch_skew_on_vt3324(
17662306a36Sopenharmony_ci	struct lvds_setting_information *plvds_setting_info,
17762306a36Sopenharmony_ci	struct lvds_chip_information *plvds_chip_info)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
18062306a36Sopenharmony_ci		*pdpa;
18162306a36Sopenharmony_ci	int index;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/* Graphics DPA settings: */
18662306a36Sopenharmony_ci	index = get_clk_range_index(plvds_setting_info->vclk);
18762306a36Sopenharmony_ci	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
18862306a36Sopenharmony_ci		    &GFX_DPA_SETTING_TBL_VT3324[index]);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	/* LVDS Transmitter DPA settings: */
19162306a36Sopenharmony_ci	if (plvds_setting_info->lcd_panel_hres == 1600 &&
19262306a36Sopenharmony_ci		plvds_setting_info->lcd_panel_vres == 1200)
19362306a36Sopenharmony_ci		pdpa = &dpa_16x12;
19462306a36Sopenharmony_ci	else
19562306a36Sopenharmony_ci		pdpa = &dpa;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_civoid viafb_vt1636_patch_skew_on_vt3327(
20162306a36Sopenharmony_ci	struct lvds_setting_information *plvds_setting_info,
20262306a36Sopenharmony_ci	struct lvds_chip_information *plvds_chip_info)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
20562306a36Sopenharmony_ci	int index;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	/* Graphics DPA settings: */
21062306a36Sopenharmony_ci	index = get_clk_range_index(plvds_setting_info->vclk);
21162306a36Sopenharmony_ci	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
21262306a36Sopenharmony_ci		    &GFX_DPA_SETTING_TBL_VT3327[index]);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	/* LVDS Transmitter DPA settings: */
21562306a36Sopenharmony_ci	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_civoid viafb_vt1636_patch_skew_on_vt3364(
21962306a36Sopenharmony_ci	struct lvds_setting_information *plvds_setting_info,
22062306a36Sopenharmony_ci	struct lvds_chip_information *plvds_chip_info)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	int index;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/* Graphics DPA settings: */
22762306a36Sopenharmony_ci	index = get_clk_range_index(plvds_setting_info->vclk);
22862306a36Sopenharmony_ci	viafb_set_dpa_gfx(plvds_chip_info->output_interface,
22962306a36Sopenharmony_ci		    &GFX_DPA_SETTING_TBL_VT3364[index]);
23062306a36Sopenharmony_ci}
231