993 lines · 30.3 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.  */#include <linux/via-core.h>#include <linux/via_i2c.h>#include "global.h" #define viafb_compact_res(x, y) (((x)<<16)|(y)) /* CLE266 Software Power Sequence *//* {Mask}, {Data}, {Delay} */static const int PowerSequenceOn[3][3] = {	{0x10, 0x08, 0x06}, {0x10, 0x08, 0x06},	{0x19, 0x1FE, 0x01}};static const int PowerSequenceOff[3][3] = {	{0x06, 0x08, 0x10}, {0x00, 0x00, 0x00},	{0xD2, 0x19, 0x01}}; static struct _lcd_scaling_factor lcd_scaling_factor = {	/* LCD Horizontal Scaling Factor Register */	{LCD_HOR_SCALING_FACTOR_REG_NUM,	 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },	/* LCD Vertical Scaling Factor Register */	{LCD_VER_SCALING_FACTOR_REG_NUM,	 {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }};static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {	/* LCD Horizontal Scaling Factor Register */	{LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },	/* LCD Vertical Scaling Factor Register */	{LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }}; static bool lvds_identify_integratedlvds(void);static void fp_id_to_vindex(int panel_id);static int lvds_register_read(int index);static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,		      int panel_vres);static void lcd_patch_skew_dvp0(struct lvds_setting_information			 *plvds_setting_info,			 struct lvds_chip_information *plvds_chip_info);static void lcd_patch_skew_dvp1(struct lvds_setting_information			 *plvds_setting_info,			 struct lvds_chip_information *plvds_chip_info);static void lcd_patch_skew(struct lvds_setting_information	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info); static void integrated_lvds_disable(struct lvds_setting_information			     *plvds_setting_info,			     struct lvds_chip_information *plvds_chip_info);static void integrated_lvds_enable(struct lvds_setting_information			    *plvds_setting_info,			    struct lvds_chip_information *plvds_chip_info);static void lcd_powersequence_off(void);static void lcd_powersequence_on(void);static void fill_lcd_format(void);static void check_diport_of_integrated_lvds(	struct lvds_chip_information *plvds_chip_info,				     struct lvds_setting_information				     *plvds_setting_info); static inline bool check_lvds_chip(int device_id_subaddr, int device_id){	return lvds_register_read(device_id_subaddr) == device_id;} void viafb_init_lcd_size(void){	DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n"); 	fp_id_to_vindex(viafb_lcd_panel_id);	viaparinfo->lvds_setting_info2->lcd_panel_hres =		viaparinfo->lvds_setting_info->lcd_panel_hres;	viaparinfo->lvds_setting_info2->lcd_panel_vres =		viaparinfo->lvds_setting_info->lcd_panel_vres;	viaparinfo->lvds_setting_info2->device_lcd_dualedge =	    viaparinfo->lvds_setting_info->device_lcd_dualedge;	viaparinfo->lvds_setting_info2->LCDDithering =		viaparinfo->lvds_setting_info->LCDDithering;} static bool lvds_identify_integratedlvds(void){	if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {		/* Two dual channel LCD (Internal LVDS + External LVDS): */		/* If we have an external LVDS, such as VT1636, we should		   have its chip ID already. */		if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {			viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =			    INTEGRATED_LVDS;			DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "				  "(Internal LVDS + External LVDS)\n");		} else {			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =			    INTEGRATED_LVDS;			DEBUG_MSG(KERN_INFO "Not found external LVDS, "				  "so can't support two dual channel LVDS!\n");		}	} else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {		/* Two single channel LCD (Internal LVDS + Internal LVDS): */		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =		INTEGRATED_LVDS;		viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =			INTEGRATED_LVDS;		DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "			  "(Internal LVDS + Internal LVDS)\n");	} else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {		/* If we have found external LVDS, just use it,		   otherwise, we will use internal LVDS as default. */		if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {			viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =			    INTEGRATED_LVDS;			DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");		}	} else {		viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =			NON_LVDS_TRANSMITTER;		DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");		return false;	} 	return true;} bool viafb_lvds_trasmitter_identify(void){	if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {		viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;		DEBUG_MSG(KERN_INFO			  "Found VIA VT1636 LVDS on port i2c 0x31\n");	} else {		if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {			viaparinfo->chip_info->lvds_chip_info.i2c_port =				VIA_PORT_2C;			DEBUG_MSG(KERN_INFO				  "Found VIA VT1636 LVDS on port gpio 0x2c\n");		}	} 	if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)		lvds_identify_integratedlvds(); 	if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)		return true;	/* Check for VT1631: */	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;	viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr =		VT1631_LVDS_I2C_ADDR; 	if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {		DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");		DEBUG_MSG(KERN_INFO "\n %2d",			  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);		DEBUG_MSG(KERN_INFO "\n %2d",			  viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);		return true;	} 	viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =		NON_LVDS_TRANSMITTER;	viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr =		VT1631_LVDS_I2C_ADDR;	return false;} static void fp_id_to_vindex(int panel_id){	DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n"); 	if (panel_id > LCD_PANEL_ID_MAXIMUM)		viafb_lcd_panel_id = panel_id =		viafb_read_reg(VIACR, CR3F) & 0x0F; 	switch (panel_id) {	case 0x0:		viaparinfo->lvds_setting_info->lcd_panel_hres = 640;		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x1:		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x2:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x3:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x4:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x5:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x6:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x8:		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x9:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0xA:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0xB:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0xC:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0xD:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0xE:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0xF:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0x10:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0x11:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x12:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x13:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 800;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x14:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0x15:		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	case 0x16:		viaparinfo->lvds_setting_info->lcd_panel_hres = 480;		viaparinfo->lvds_setting_info->lcd_panel_vres = 640;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;		break;	case 0x17:		/* OLPC XO-1.5 panel */		viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;		viaparinfo->lvds_setting_info->lcd_panel_vres = 900;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 0;		break;	default:		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;		viaparinfo->lvds_setting_info->LCDDithering = 1;	}} static int lvds_register_read(int index){	u8 data; 	viafb_i2c_readbyte(VIA_PORT_2C,			(u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr,			(u8) index, &data);	return data;} static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,		      int panel_vres){	int reg_value = 0;	int viafb_load_reg_num;	struct io_register *reg = NULL; 	DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n"); 	/* LCD Scaling Enable */	viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2); 	/* Check if expansion for horizontal */	if (set_hres < panel_hres) {		/* Load Horizontal Scaling Factor */		switch (viaparinfo->chip_info->gfx_chip_name) {		case UNICHROME_CLE266:		case UNICHROME_K400:			reg_value =			    CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);			viafb_load_reg_num =			    lcd_scaling_factor_CLE.lcd_hor_scaling_factor.			    reg_num;			reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;			viafb_load_reg(reg_value,				viafb_load_reg_num, reg, VIACR);			break;		case UNICHROME_K800:		case UNICHROME_PM800:		case UNICHROME_CN700:		case UNICHROME_CX700:		case UNICHROME_K8M890:		case UNICHROME_P4M890:		case UNICHROME_P4M900:		case UNICHROME_CN750:		case UNICHROME_VX800:		case UNICHROME_VX855:		case UNICHROME_VX900:			reg_value =			    K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);			/* Horizontal scaling enabled */			viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);			viafb_load_reg_num =			    lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;			reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;			viafb_load_reg(reg_value,				viafb_load_reg_num, reg, VIACR);			break;		} 		DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);	} else {		/* Horizontal scaling disabled */		viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);	} 	/* Check if expansion for vertical */	if (set_vres < panel_vres) {		/* Load Vertical Scaling Factor */		switch (viaparinfo->chip_info->gfx_chip_name) {		case UNICHROME_CLE266:		case UNICHROME_K400:			reg_value =			    CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);			viafb_load_reg_num =			    lcd_scaling_factor_CLE.lcd_ver_scaling_factor.			    reg_num;			reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;			viafb_load_reg(reg_value,				viafb_load_reg_num, reg, VIACR);			break;		case UNICHROME_K800:		case UNICHROME_PM800:		case UNICHROME_CN700:		case UNICHROME_CX700:		case UNICHROME_K8M890:		case UNICHROME_P4M890:		case UNICHROME_P4M900:		case UNICHROME_CN750:		case UNICHROME_VX800:		case UNICHROME_VX855:		case UNICHROME_VX900:			reg_value =			    K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);			/* Vertical scaling enabled */			viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);			viafb_load_reg_num =			    lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;			reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;			viafb_load_reg(reg_value,				viafb_load_reg_num, reg, VIACR);			break;		} 		DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);	} else {		/* Vertical scaling disabled */		viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);	}} static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp){	unsigned char cr13, cr35, cr65, cr66, cr67;	unsigned long dwScreenPitch = 0;	unsigned long dwPitch; 	dwPitch = hres * (bpp >> 3);	if (dwPitch & 0x1F) {		dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;		if (iga_path == IGA2) {			if (bpp > 8) {				cr66 = (unsigned char)(dwScreenPitch & 0xFF);				viafb_write_reg(CR66, VIACR, cr66);				cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;				cr67 |=				    (unsigned				     char)((dwScreenPitch & 0x300) >> 8);				viafb_write_reg(CR67, VIACR, cr67);			} 			/* Fetch Count */			cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;			cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);			viafb_write_reg(CR67, VIACR, cr67);			cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);			cr65 += 2;			viafb_write_reg(CR65, VIACR, cr65);		} else {			if (bpp > 8) {				cr13 = (unsigned char)(dwScreenPitch & 0xFF);				viafb_write_reg(CR13, VIACR, cr13);				cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;				cr35 |=				    (unsigned				     char)((dwScreenPitch & 0x700) >> 3);				viafb_write_reg(CR35, VIACR, cr35);			}		}	}}static void lcd_patch_skew_dvp0(struct lvds_setting_information			 *plvds_setting_info,			 struct lvds_chip_information *plvds_chip_info){	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {		switch (viaparinfo->chip_info->gfx_chip_name) {		case UNICHROME_P4M900:			viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,						    plvds_chip_info);			break;		case UNICHROME_P4M890:			viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,						    plvds_chip_info);			break;		}	}}static void lcd_patch_skew_dvp1(struct lvds_setting_information			 *plvds_setting_info,			 struct lvds_chip_information *plvds_chip_info){	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {		switch (viaparinfo->chip_info->gfx_chip_name) {		case UNICHROME_CX700:			viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,

Lines 1–500 of 993.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t