staging: sm750fb: add sm750 to staging
sm750 of Silicon Motion is pci-e display controller device and has features like dual display and 2D acceleration. This patch adds the driver to staging. Signed-off-by: Sudip Mukherjee <sudip@vectorindia.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									c3d6047d95
								
							
						
					
					
						commit
						81dee67e21
					
				| @ -58,6 +58,8 @@ source "drivers/staging/iio/Kconfig" | ||||
| 
 | ||||
| source "drivers/staging/sm7xxfb/Kconfig" | ||||
| 
 | ||||
| source "drivers/staging/sm750fb/Kconfig" | ||||
| 
 | ||||
| source "drivers/staging/xgifb/Kconfig" | ||||
| 
 | ||||
| source "drivers/staging/emxx_udc/Kconfig" | ||||
|  | ||||
| @ -23,6 +23,7 @@ obj-$(CONFIG_VT6656)		+= vt6656/ | ||||
| obj-$(CONFIG_VME_BUS)		+= vme/ | ||||
| obj-$(CONFIG_IIO)		+= iio/ | ||||
| obj-$(CONFIG_FB_SM7XX)		+= sm7xxfb/ | ||||
| obj-$(CONFIG_FB_SM7XX)		+= sm750fb/ | ||||
| obj-$(CONFIG_FB_XGI)		+= xgifb/ | ||||
| obj-$(CONFIG_USB_EMXX)		+= emxx_udc/ | ||||
| obj-$(CONFIG_FT1000)		+= ft1000/ | ||||
|  | ||||
							
								
								
									
										10
									
								
								drivers/staging/sm750fb/Kconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								drivers/staging/sm750fb/Kconfig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| config FB_SM750 | ||||
| 	tristate "Silicon Motion SM750 framebuffer support" | ||||
| 	depends on FB && PCI | ||||
| 	help | ||||
| 	  Frame buffer driver for the Silicon Motion SM750 chip | ||||
| 	  with 2D accelearion and dual head support. | ||||
| 
 | ||||
| 	  This driver is also available as a module. The module will be | ||||
| 	  called sm750fb. If you want to compile it as a module, say M | ||||
| 	  here and read <file:Documentation/kbuild/modules.txt>. | ||||
							
								
								
									
										4
									
								
								drivers/staging/sm750fb/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								drivers/staging/sm750fb/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| obj-$(CONFIG_FB_SM750)	+= sm750fb.o | ||||
| 
 | ||||
| sm750fb-objs		:= sm750.o sm750_hw.o sm750_accel.o sm750_cursor.o ddk750_chip.o ddk750_power.o ddk750_mode.o | ||||
| sm750fb-objs		+= ddk750_display.o ddk750_help.o ddk750_swi2c.o ddk750_sii164.o ddk750_dvi.o ddk750_hwi2c.o | ||||
							
								
								
									
										15
									
								
								drivers/staging/sm750fb/TODO
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								drivers/staging/sm750fb/TODO
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| TODO: | ||||
| - lots of clechpatch cleanup | ||||
| - use kernel coding style | ||||
| - refine the code and remove unused code | ||||
| - check on hardware effects of removal of USE_HW_I2C and USE_DVICHIP (these two | ||||
| 	are supposed to be sample code which is given here if someone wants to | ||||
| 	use those functionalities) | ||||
| - move it to drivers/video/fbdev | ||||
| - modify the code for drm framework | ||||
| 
 | ||||
| Please send any patches to | ||||
| 	Greg Kroah-Hartman <greg@kroah.com> | ||||
| 	Sudip Mukherjee <sudipm.mukherjee@gmail.com> | ||||
| 	Teddy Wang <teddy.wang@siliconmotion.com> | ||||
| 	Sudip Mukherjee <sudip@vectorindia.org> | ||||
							
								
								
									
										24
									
								
								drivers/staging/sm750fb/ddk750.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								drivers/staging/sm750fb/ddk750.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| #ifndef DDK750_H__ | ||||
| #define DDK750_H__ | ||||
| /*******************************************************************
 | ||||
| * | ||||
| *         Copyright (c) 2007 by Silicon Motion, Inc. (SMI) | ||||
| * | ||||
| *  All rights are reserved. Reproduction or in part is prohibited | ||||
| *  without the written consent of the copyright owner. | ||||
| * | ||||
| *  RegSC.h --- SM718 SDK | ||||
| *  This file contains the definitions for the System Configuration registers. | ||||
| * | ||||
| *******************************************************************/ | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_mode.h" | ||||
| #include "ddk750_chip.h" | ||||
| #include "ddk750_display.h" | ||||
| #include "ddk750_power.h" | ||||
| #include "ddk750_help.h" | ||||
| #ifdef USE_HW_I2C | ||||
| #include "ddk750_hwi2c.h" | ||||
| #endif | ||||
| #include "ddk750_swi2c.h" | ||||
| #endif | ||||
							
								
								
									
										639
									
								
								drivers/staging/sm750fb/ddk750_chip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										639
									
								
								drivers/staging/sm750fb/ddk750_chip.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,639 @@ | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_chip.h" | ||||
| #include "ddk750_power.h" | ||||
| typedef struct _pllcalparam{ | ||||
| 	unsigned char power;/* d : 0~ 6*/ | ||||
| 	unsigned char pod; | ||||
| 	unsigned char od; | ||||
| 	unsigned char value;/* value of  2 power d (2^d) */ | ||||
| } | ||||
| pllcalparam; | ||||
| 
 | ||||
| 
 | ||||
| logical_chip_type_t getChipType() | ||||
| { | ||||
| 	unsigned short physicalID; | ||||
| 	char physicalRev; | ||||
| 	logical_chip_type_t chip; | ||||
| 
 | ||||
| 	physicalID = devId750;//either 0x718 or 0x750
 | ||||
| 	physicalRev = revId750; | ||||
| 
 | ||||
|     if (physicalID == 0x718) | ||||
|     { | ||||
|         chip = SM718; | ||||
|     } | ||||
|     else if (physicalID == 0x750) | ||||
|     { | ||||
|         chip = SM750; | ||||
| 		/* SM750 and SM750LE are different in their revision ID only. */ | ||||
| 		if (physicalRev == SM750LE_REVISION_ID){ | ||||
| 			chip = SM750LE; | ||||
| 		} | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         chip = SM_UNKNOWN; | ||||
|     } | ||||
| 
 | ||||
| 	return chip; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| inline unsigned int twoToPowerOfx(unsigned long x) | ||||
| { | ||||
|     unsigned long i; | ||||
|     unsigned long result = 1; | ||||
| 
 | ||||
|     for (i=1; i<=x; i++) | ||||
|         result *= 2; | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| inline unsigned int calcPLL(pll_value_t *pPLL) | ||||
| { | ||||
|     return (pPLL->inputFreq * pPLL->M / pPLL->N / twoToPowerOfx(pPLL->OD) / twoToPowerOfx(pPLL->POD)); | ||||
| } | ||||
| 
 | ||||
| unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL) | ||||
| { | ||||
|     unsigned int ulPllReg = 0; | ||||
| 
 | ||||
|     pPLL->inputFreq = DEFAULT_INPUT_CLOCK; | ||||
|     pPLL->clockType = clockType; | ||||
| 
 | ||||
|     switch (clockType) | ||||
|     { | ||||
|         case MXCLK_PLL: | ||||
|             ulPllReg = PEEK32(MXCLK_PLL_CTRL); | ||||
|             break; | ||||
|         case PRIMARY_PLL: | ||||
|             ulPllReg = PEEK32(PANEL_PLL_CTRL); | ||||
|             break; | ||||
|         case SECONDARY_PLL: | ||||
|             ulPllReg = PEEK32(CRT_PLL_CTRL); | ||||
|             break; | ||||
|         case VGA0_PLL: | ||||
|             ulPllReg = PEEK32(VGA_PLL0_CTRL); | ||||
|             break; | ||||
|         case VGA1_PLL: | ||||
|             ulPllReg = PEEK32(VGA_PLL1_CTRL); | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     pPLL->M = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, M); | ||||
|     pPLL->N = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, N); | ||||
|     pPLL->OD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, OD); | ||||
|     pPLL->POD = FIELD_GET(ulPllReg, PANEL_PLL_CTRL, POD); | ||||
| 
 | ||||
|     return calcPLL(pPLL); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| unsigned int getChipClock() | ||||
| { | ||||
|     pll_value_t pll; | ||||
| #if 1 | ||||
| 	if(getChipType() == SM750LE) | ||||
| 		return MHz(130); | ||||
| #endif | ||||
| 
 | ||||
|     return getPllValue(MXCLK_PLL, &pll); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function set up the main chip clock. | ||||
|  * | ||||
|  * Input: Frequency to be set. | ||||
|  */ | ||||
| void setChipClock(unsigned int frequency) | ||||
| { | ||||
|     pll_value_t pll; | ||||
|     unsigned int ulActualMxClk; | ||||
| #if 1 | ||||
| 		/* Cheok_0509: For SM750LE, the chip clock is fixed. Nothing to set. */ | ||||
| 		if (getChipType() == SM750LE) | ||||
| 			return; | ||||
| #endif | ||||
| 
 | ||||
|     if (frequency != 0) | ||||
|     { | ||||
|         /*
 | ||||
|          * Set up PLL, a structure to hold the value to be set in clocks. | ||||
|          */ | ||||
|         pll.inputFreq = DEFAULT_INPUT_CLOCK; /* Defined in CLOCK.H */ | ||||
|         pll.clockType = MXCLK_PLL; | ||||
| 
 | ||||
|         /*
 | ||||
|          * Call calcPllValue() to fill up the other fields for PLL structure. | ||||
|          * Sometime, the chip cannot set up the exact clock required by User. | ||||
|          * Return value from calcPllValue() gives the actual possible clock. | ||||
|          */ | ||||
|         ulActualMxClk = calcPllValue(frequency, &pll); | ||||
| 
 | ||||
|         /* Master Clock Control: MXCLK_PLL */ | ||||
|         POKE32(MXCLK_PLL_CTRL, formatPllReg(&pll)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void setMemoryClock(unsigned int frequency) | ||||
| { | ||||
|     unsigned int ulReg, divisor; | ||||
|  #if 1 | ||||
| 	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ | ||||
| 	if (getChipType() == SM750LE) | ||||
| 		return; | ||||
| #endif | ||||
|     if (frequency != 0) | ||||
|     { | ||||
|         /* Set the frequency to the maximum frequency that the DDR Memory can take
 | ||||
|            which is 336MHz. */ | ||||
|         if (frequency > MHz(336)) | ||||
|             frequency = MHz(336); | ||||
| 
 | ||||
|         /* Calculate the divisor */ | ||||
|         divisor = (unsigned int) roundedDiv(getChipClock(), frequency); | ||||
| 
 | ||||
|         /* Set the corresponding divisor in the register. */ | ||||
|         ulReg = PEEK32(CURRENT_GATE); | ||||
|         switch(divisor) | ||||
|         { | ||||
|             default: | ||||
|             case 1: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1); | ||||
|                 break; | ||||
|             case 2: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2); | ||||
|                 break; | ||||
|             case 3: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3); | ||||
|                 break; | ||||
|             case 4: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4); | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         setCurrentGate(ulReg); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function set up the master clock (MCLK). | ||||
|  * | ||||
|  * Input: Frequency to be set. | ||||
|  * | ||||
|  * NOTE: | ||||
|  *      The maximum frequency the engine can run is 168MHz. | ||||
|  */ | ||||
| void setMasterClock(unsigned int frequency) | ||||
| { | ||||
|     unsigned int ulReg, divisor; | ||||
|   #if 1 | ||||
| 	/* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ | ||||
| 	if (getChipType() == SM750LE) | ||||
| 		return; | ||||
| #endif | ||||
|     if (frequency != 0) | ||||
|     { | ||||
|         /* Set the frequency to the maximum frequency that the SM750 engine can
 | ||||
|            run, which is about 190 MHz. */ | ||||
|         if (frequency > MHz(190)) | ||||
|             frequency = MHz(190); | ||||
| 
 | ||||
|         /* Calculate the divisor */ | ||||
|         divisor = (unsigned int) roundedDiv(getChipClock(), frequency); | ||||
| 
 | ||||
|         /* Set the corresponding divisor in the register. */ | ||||
|         ulReg = PEEK32(CURRENT_GATE); | ||||
|         switch(divisor) | ||||
|         { | ||||
|             default: | ||||
|             case 3: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3); | ||||
|                 break; | ||||
|             case 4: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4); | ||||
|                 break; | ||||
|             case 6: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6); | ||||
|                 break; | ||||
|             case 8: | ||||
|                 ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8); | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         setCurrentGate(ulReg); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| unsigned int ddk750_getVMSize() | ||||
| { | ||||
| 	unsigned int reg; | ||||
| 	unsigned int data; | ||||
| 
 | ||||
| 	/* sm750le only use 64 mb memory*/ | ||||
| 	if(getChipType() == SM750LE) | ||||
| 		return MB(64); | ||||
| 
 | ||||
| 	/* for 750,always use power mode0*/ | ||||
| 	reg = PEEK32(MODE0_GATE); | ||||
| 	reg = FIELD_SET(reg,MODE0_GATE,GPIO,ON); | ||||
| 	POKE32(MODE0_GATE,reg); | ||||
| 
 | ||||
| 	/* get frame buffer size from GPIO */ | ||||
| 	reg = FIELD_GET(PEEK32(MISC_CTRL),MISC_CTRL,LOCALMEM_SIZE); | ||||
| 	switch(reg){ | ||||
|         case MISC_CTRL_LOCALMEM_SIZE_8M:  data = MB(8);  break; /* 8  Mega byte */ | ||||
|         case MISC_CTRL_LOCALMEM_SIZE_16M: data = MB(16); break; /* 16 Mega byte */ | ||||
|         case MISC_CTRL_LOCALMEM_SIZE_32M: data = MB(32); break; /* 32 Mega byte */ | ||||
|         case MISC_CTRL_LOCALMEM_SIZE_64M: data = MB(64); break; /* 64 Mega byte */ | ||||
| 		default: data = 0;break; | ||||
| 	} | ||||
| 	return data; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| int ddk750_initHw(initchip_param_t * pInitParam) | ||||
| { | ||||
| 
 | ||||
| 	unsigned int ulReg; | ||||
| #if 0 | ||||
| 	//move the code to map regiter function.
 | ||||
| 	if(getChipType() == SM718){ | ||||
| 		/* turn on big endian bit*/ | ||||
| 		ulReg = PEEK32(0x74); | ||||
| 		/* now consider register definition in a big endian pattern*/ | ||||
| 		POKE32(0x74,ulReg|0x80000000); | ||||
| 	} | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 	if (pInitParam->powerMode != 0 ) | ||||
| 		pInitParam->powerMode = 0; | ||||
| 	setPowerMode(pInitParam->powerMode); | ||||
| 
 | ||||
| 	/* Enable display power gate & LOCALMEM power gate*/ | ||||
| 	ulReg = PEEK32(CURRENT_GATE); | ||||
| 	ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON); | ||||
| 	ulReg = FIELD_SET(ulReg,CURRENT_GATE,LOCALMEM,ON); | ||||
| 	setCurrentGate(ulReg); | ||||
| 
 | ||||
| 	if(getChipType() != SM750LE){ | ||||
| 		/*	set panel pll and graphic mode via mmio_88 */ | ||||
| 		ulReg = PEEK32(VGA_CONFIGURATION); | ||||
| 		ulReg = FIELD_SET(ulReg,VGA_CONFIGURATION,PLL,PANEL); | ||||
| 		ulReg = FIELD_SET(ulReg,VGA_CONFIGURATION,MODE,GRAPHIC); | ||||
| 		POKE32(VGA_CONFIGURATION,ulReg); | ||||
| 	}else{ | ||||
| #if defined(__i386__) || defined( __x86_64__) | ||||
| 		/* set graphic mode via IO method */ | ||||
| 		outb_p(0x88,0x3d4); | ||||
| 		outb_p(0x06,0x3d5); | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set the Main Chip Clock */ | ||||
| 	setChipClock(MHz((unsigned int)pInitParam->chipClock)); | ||||
| 
 | ||||
| 	/* Set up memory clock. */ | ||||
| 	setMemoryClock(MHz(pInitParam->memClock)); | ||||
| 
 | ||||
| 	/* Set up master clock */ | ||||
| 	setMasterClock(MHz(pInitParam->masterClock)); | ||||
| 
 | ||||
| 
 | ||||
| 	/* Reset the memory controller. If the memory controller is not reset in SM750,
 | ||||
| 	   the system might hang when sw accesses the memory. | ||||
| 	   The memory should be resetted after changing the MXCLK. | ||||
| 	 */ | ||||
| 	if (pInitParam->resetMemory == 1) | ||||
| 	{ | ||||
| 		ulReg = PEEK32(MISC_CTRL); | ||||
| 		ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET); | ||||
| 		POKE32(MISC_CTRL, ulReg); | ||||
| 
 | ||||
| 		ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL); | ||||
| 		POKE32(MISC_CTRL, ulReg); | ||||
| 	} | ||||
| 
 | ||||
| 	if (pInitParam->setAllEngOff == 1) | ||||
| 	{ | ||||
| 		enable2DEngine(0); | ||||
| 
 | ||||
| 		/* Disable Overlay, if a former application left it on */ | ||||
| 		ulReg = PEEK32(VIDEO_DISPLAY_CTRL); | ||||
| 		ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); | ||||
| 		POKE32(VIDEO_DISPLAY_CTRL, ulReg); | ||||
| 
 | ||||
| 		/* Disable video alpha, if a former application left it on */ | ||||
| 		ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); | ||||
| 		ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); | ||||
| 		POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg); | ||||
| 
 | ||||
| 		/* Disable alpha plane, if a former application left it on */ | ||||
| 		ulReg = PEEK32(ALPHA_DISPLAY_CTRL); | ||||
| 		ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); | ||||
| 		POKE32(ALPHA_DISPLAY_CTRL, ulReg); | ||||
| 
 | ||||
| #if 0 | ||||
| 		/* Disable LCD hardware cursor, if a former application left it on */ | ||||
| 		ulReg = PEEK32(PANEL_HWC_ADDRESS); | ||||
| 		ulReg = FIELD_SET(ulReg, PANEL_HWC_ADDRESS, ENABLE, DISABLE); | ||||
| 		POKE32(PANEL_HWC_ADDRESS, ulReg); | ||||
| 
 | ||||
| 		/* Disable CRT hardware cursor, if a former application left it on */ | ||||
| 		ulReg = PEEK32(CRT_HWC_ADDRESS); | ||||
| 		ulReg = FIELD_SET(ulReg, CRT_HWC_ADDRESS, ENABLE, DISABLE); | ||||
| 		POKE32(CRT_HWC_ADDRESS, ulReg); | ||||
| 
 | ||||
| 		/* Disable ZV Port 0, if a former application left it on */ | ||||
| 		ulReg = PEEK32(ZV0_CAPTURE_CTRL); | ||||
| 		ulReg = FIELD_SET(ulReg, ZV0_CAPTURE_CTRL, CAP, DISABLE); | ||||
| 		POKE32(ZV0_CAPTURE_CTRL, ulReg); | ||||
| 
 | ||||
| 		/* Disable ZV Port 1, if a former application left it on */ | ||||
| 		ulReg = PEEK32(ZV1_CAPTURE_CTRL); | ||||
| 		ulReg = FIELD_SET(ulReg, ZV1_CAPTURE_CTRL, CAP, DISABLE); | ||||
| 		POKE32(ZV1_CAPTURE_CTRL, ulReg); | ||||
| 
 | ||||
| 		/* Disable ZV Port Power, if a former application left it on */ | ||||
| 		enableZVPort(0); | ||||
| 		/* Disable DMA Channel, if a former application left it on */ | ||||
| 		ulReg = PEEK32(DMA_ABORT_INTERRUPT); | ||||
| 		ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); | ||||
| 		POKE32(DMA_ABORT_INTERRUPT, ulReg); | ||||
| 
 | ||||
| 		/* Disable i2c */ | ||||
| 		enableI2C(0); | ||||
| #endif | ||||
| 		/* Disable DMA Channel, if a former application left it on */ | ||||
| 		ulReg = PEEK32(DMA_ABORT_INTERRUPT); | ||||
| 		ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); | ||||
| 		POKE32(DMA_ABORT_INTERRUPT, ulReg); | ||||
| 
 | ||||
| 		/* Disable DMA Power, if a former application left it on */ | ||||
| 		enableDMA(0); | ||||
| 	} | ||||
| 
 | ||||
| 	/* We can add more initialization as needed. */ | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| 
 | ||||
| unsigned int absDiff(unsigned int a, unsigned int b) | ||||
| { | ||||
|     if ( a > b ) | ||||
|         return(a - b); | ||||
|     else | ||||
|         return(b - a); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| /*
 | ||||
| 	monk liu @ 4/6/2011: | ||||
| 		   re-write the calculatePLL function of ddk750. | ||||
| 		   the original version function does not use some mathematics tricks and shortcut | ||||
| 		   when it doing the calculation of the best N,M,D combination | ||||
| 		   I think this version gives a little upgrade in speed | ||||
| 
 | ||||
| 	750 pll clock formular: | ||||
| 	Request Clock = (Input Clock * M )/(N * X) | ||||
| 
 | ||||
| 	Input Clock = 14318181 hz | ||||
| 	X = 2 power D | ||||
| 	D ={0,1,2,3,4,5,6} | ||||
| 	M = {1,...,255} | ||||
| 	N = {2,...,15} | ||||
| */ | ||||
| unsigned int calcPllValue(unsigned int request_orig,pll_value_t *pll) | ||||
| { | ||||
| 	/* used for primary and secondary channel pixel clock pll */ | ||||
| 	static pllcalparam xparm_PIXEL[] = { | ||||
| 		/* 2^0 = 1*/			{0,0,0,1}, | ||||
| 		/* 2^ 1 =2*/			{1,0,1,2}, | ||||
| 		/* 2^ 2  = 4*/		{2,0,2,4}, | ||||
| 							{3,0,3,8}, | ||||
| 							{4,1,3,16}, | ||||
| 							{5,2,3,32}, | ||||
| 		/* 2^6 = 64  */		{6,3,3,64}, | ||||
| 							}; | ||||
| 
 | ||||
| 	/* used for MXCLK (chip clock) */ | ||||
| 	static pllcalparam xparm_MXCLK[] = { | ||||
| 		/* 2^0 = 1*/			{0,0,0,1}, | ||||
| 		/* 2^ 1 =2*/			{1,0,1,2}, | ||||
| 		/* 2^ 2  = 4*/		{2,0,2,4}, | ||||
| 							{3,0,3,8}, | ||||
| 							}; | ||||
| 
 | ||||
| 	/* 	as sm750 register definition, N located in 2,15 and M located in 1,255	*/ | ||||
| 	int N,M,X,d; | ||||
| 	int xcnt; | ||||
| 	int miniDiff; | ||||
| 	unsigned int RN,quo,rem,fl_quo; | ||||
| 	unsigned int input,request; | ||||
| 	unsigned int tmpClock,ret; | ||||
| 	pllcalparam * xparm; | ||||
| 
 | ||||
| #if 1 | ||||
| 	if (getChipType() == SM750LE) | ||||
|     { | ||||
|         /* SM750LE don't have prgrammable PLL and M/N values to work on.
 | ||||
|            Just return the requested clock. */ | ||||
|         return request_orig; | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
| 	ret = 0; | ||||
| 	miniDiff = ~0; | ||||
| 	request = request_orig / 1000; | ||||
| 	input = pll->inputFreq / 1000; | ||||
| 
 | ||||
| 	/* for MXCLK register , no POD provided, so need be treated differently	*/ | ||||
| 
 | ||||
| 	if(pll->clockType != MXCLK_PLL){ | ||||
| 		xparm = &xparm_PIXEL[0]; | ||||
| 		xcnt = sizeof(xparm_PIXEL)/sizeof(xparm_PIXEL[0]); | ||||
| 	}else{ | ||||
| 		xparm = &xparm_MXCLK[0]; | ||||
| 		xcnt = sizeof(xparm_MXCLK)/sizeof(xparm_MXCLK[0]); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	for(N = 15;N>1;N--) | ||||
| 	{ | ||||
| 		/* RN will not exceed maximum long if @request <= 285 MHZ (for 32bit cpu) */ | ||||
| 		RN = N * request; | ||||
| 		quo = RN / input; | ||||
| 		rem = RN % input;/* rem always small than 14318181 */ | ||||
| 		fl_quo = (rem * 10000 /input); | ||||
| 
 | ||||
| 		for(d = xcnt - 1;d >= 0;d--){ | ||||
| 			X = xparm[d].value; | ||||
| 			M = quo*X; | ||||
| 			M += fl_quo * X / 10000; | ||||
| 			/* round step */ | ||||
| 			M += (fl_quo*X % 10000)>5000?1:0; | ||||
| 			if(M < 256 && M > 0) | ||||
| 			{ | ||||
| 				unsigned int diff; | ||||
| 				tmpClock = pll->inputFreq *M / N / X; | ||||
|                 diff = absDiff(tmpClock,request_orig); | ||||
| 				if(diff < miniDiff) | ||||
| 				{ | ||||
| 					pll->M = M; | ||||
| 					pll->N = N; | ||||
| 					pll->OD = xparm[d].od; | ||||
| 					pll->POD = xparm[d].pod; | ||||
| 					miniDiff = diff; | ||||
| 					ret = tmpClock; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	//printk("Finally:  pll->n[%lu],m[%lu],od[%lu],pod[%lu]\n",pll->N,pll->M,pll->OD,pll->POD);
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| unsigned int calcPllValue2( | ||||
| unsigned int ulRequestClk, /* Required pixel clock in Hz unit */ | ||||
| pll_value_t *pPLL           /* Structure to hold the value to be set in PLL */ | ||||
| ) | ||||
| { | ||||
|     unsigned int M, N, OD, POD = 0, diff, pllClk, odPower, podPower; | ||||
|     unsigned int bestDiff = 0xffffffff; /* biggest 32 bit unsigned number */ | ||||
| 	unsigned int ret; | ||||
|     /* Init PLL structure to know states */ | ||||
|     pPLL->M = 0; | ||||
|     pPLL->N = 0; | ||||
|     pPLL->OD = 0; | ||||
|     pPLL->POD = 0; | ||||
| 
 | ||||
|     /* Sanity check: None at the moment */ | ||||
| 
 | ||||
|     /* Convert everything in Khz range in order to avoid calculation overflow */ | ||||
|     pPLL->inputFreq /= 1000; | ||||
|     ulRequestClk /= 1000; | ||||
| 
 | ||||
| #ifndef VALIDATION_CHIP | ||||
|     /* The maximum of post divider is 8. */ | ||||
|     for (POD=0; POD<=3; POD++) | ||||
| #endif | ||||
|     { | ||||
| 
 | ||||
| #ifndef VALIDATION_CHIP | ||||
|         /* MXCLK_PLL does not have post divider. */ | ||||
|         if ((POD > 0) && (pPLL->clockType == MXCLK_PLL)) | ||||
|             break; | ||||
| #endif | ||||
| 
 | ||||
|         /* Work out 2 to the power of POD */ | ||||
|         podPower = twoToPowerOfx(POD); | ||||
| 
 | ||||
|         /* OD has only 2 bits [15:14] and its value must between 0 to 3 */ | ||||
|         for (OD=0; OD<=3; OD++) | ||||
|         { | ||||
|             /* Work out 2 to the power of OD */ | ||||
|             odPower = twoToPowerOfx(OD); | ||||
| 
 | ||||
| #ifdef VALIDATION_CHIP | ||||
|             if (odPower > 4) | ||||
|                 podPower = 4; | ||||
|             else | ||||
|                 podPower = odPower; | ||||
| #endif | ||||
| 
 | ||||
|             /* N has 4 bits [11:8] and its value must between 2 and 15.
 | ||||
|                The N == 1 will behave differently --> Result is not correct. */ | ||||
|             for (N=2; N<=15; N++) | ||||
|             { | ||||
|                 /* The formula for PLL is ulRequestClk = inputFreq * M / N / (2^OD)
 | ||||
|                    In the following steps, we try to work out a best M value given the others are known. | ||||
|                    To avoid decimal calculation, we use 1000 as multiplier for up to 3 decimal places of accuracy. | ||||
|                 */ | ||||
|                 M = ulRequestClk * N * odPower * 1000 / pPLL->inputFreq; | ||||
|                 M = roundedDiv(M, 1000); | ||||
| 
 | ||||
|                 /* M field has only 8 bits, reject value bigger than 8 bits */ | ||||
|                 if (M < 256) | ||||
|                 { | ||||
|                     /* Calculate the actual clock for a given M & N */ | ||||
|                     pllClk = pPLL->inputFreq * M / N / odPower / podPower; | ||||
| 
 | ||||
|                     /* How much are we different from the requirement */ | ||||
|                     diff = absDiff(pllClk, ulRequestClk); | ||||
| 
 | ||||
|                     if (diff < bestDiff) | ||||
|                     { | ||||
|                         bestDiff = diff; | ||||
| 
 | ||||
|                         /* Store M and N values */ | ||||
|                         pPLL->M  = M; | ||||
|                         pPLL->N  = N; | ||||
|                         pPLL->OD = OD; | ||||
| 
 | ||||
| #ifdef VALIDATION_CHIP | ||||
|                         if (OD > 2) | ||||
|                             POD = 2; | ||||
|                         else | ||||
|                             POD = OD; | ||||
| #endif | ||||
| 
 | ||||
|                         pPLL->POD = POD; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* Restore input frequency from Khz to hz unit */ | ||||
| //    pPLL->inputFreq *= 1000;
 | ||||
|     ulRequestClk *= 1000; | ||||
|     pPLL->inputFreq = DEFAULT_INPUT_CLOCK; /* Default reference clock */ | ||||
| 
 | ||||
|     /* Output debug information */ | ||||
|     //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Requested Frequency = %d\n", ulRequestClk));
 | ||||
|     //DDKDEBUGPRINT((DISPLAY_LEVEL, "calcPllValue: Input CLK = %dHz, M=%d, N=%d, OD=%d, POD=%d\n", pPLL->inputFreq, pPLL->M, pPLL->N, pPLL->OD, pPLL->POD));
 | ||||
| 
 | ||||
|     /* Return actual frequency that the PLL can set */ | ||||
| 	ret = calcPLL(pPLL); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| unsigned int formatPllReg(pll_value_t *pPLL) | ||||
| { | ||||
|     unsigned int ulPllReg = 0; | ||||
| 
 | ||||
|     /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter
 | ||||
|        to work out the bit fields in the register. | ||||
|        On returning a 32 bit number, the value can be applied to any PLL in the calling function. | ||||
|     */ | ||||
|     ulPllReg = | ||||
|         FIELD_SET(  0, PANEL_PLL_CTRL, BYPASS, OFF) | ||||
|       | FIELD_SET(  0, PANEL_PLL_CTRL, POWER,  ON) | ||||
|       | FIELD_SET(  0, PANEL_PLL_CTRL, INPUT,  OSC) | ||||
| #ifndef VALIDATION_CHIP | ||||
|       | FIELD_VALUE(0, PANEL_PLL_CTRL, POD,    pPLL->POD) | ||||
| #endif | ||||
|       | FIELD_VALUE(0, PANEL_PLL_CTRL, OD,     pPLL->OD) | ||||
|       | FIELD_VALUE(0, PANEL_PLL_CTRL, N,      pPLL->N) | ||||
|       | FIELD_VALUE(0, PANEL_PLL_CTRL, M,      pPLL->M); | ||||
| 
 | ||||
|     return(ulPllReg); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										83
									
								
								drivers/staging/sm750fb/ddk750_chip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								drivers/staging/sm750fb/ddk750_chip.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,83 @@ | ||||
| #ifndef DDK750_CHIP_H__ | ||||
| #define DDK750_CHIP_H__ | ||||
| #define DEFAULT_INPUT_CLOCK 14318181 /* Default reference clock */ | ||||
| #define SM750LE_REVISION_ID (char)0xfe | ||||
| 
 | ||||
| /* This is all the chips recognized by this library */ | ||||
| typedef enum _logical_chip_type_t | ||||
| { | ||||
|     SM_UNKNOWN, | ||||
|     SM718, | ||||
|     SM750, | ||||
|     SM750LE, | ||||
| } | ||||
| logical_chip_type_t; | ||||
| 
 | ||||
| 
 | ||||
| typedef enum _clock_type_t | ||||
| { | ||||
| 	MXCLK_PLL, | ||||
| 	PRIMARY_PLL, | ||||
| 	SECONDARY_PLL, | ||||
| 	VGA0_PLL, | ||||
| 	VGA1_PLL, | ||||
| } | ||||
| clock_type_t; | ||||
| 
 | ||||
| typedef struct _pll_value_t | ||||
| { | ||||
|     clock_type_t clockType; | ||||
|     unsigned long inputFreq; /* Input clock frequency to the PLL */ | ||||
| 
 | ||||
|     /* Use this when clockType = PANEL_PLL */ | ||||
|     unsigned long M; | ||||
|     unsigned long N; | ||||
|     unsigned long OD; | ||||
|     unsigned long POD; | ||||
| } | ||||
| pll_value_t; | ||||
| 
 | ||||
| /* input struct to initChipParam() function */ | ||||
| typedef struct _initchip_param_t | ||||
| { | ||||
|     unsigned short powerMode;    /* Use power mode 0 or 1 */ | ||||
|     unsigned short chipClock;    /* Speed of main chip clock in MHz unit
 | ||||
|                                     0 = keep the current clock setting | ||||
|                                     Others = the new main chip clock | ||||
|                                   */ | ||||
|     unsigned short memClock;     /* Speed of memory clock in MHz unit
 | ||||
|                                     0 = keep the current clock setting | ||||
|                                     Others = the new memory clock | ||||
|                                   */ | ||||
|     unsigned short masterClock;  /* Speed of master clock in MHz unit
 | ||||
|                                     0 = keep the current clock setting | ||||
|                                     Others = the new master clock | ||||
|                                   */ | ||||
|     unsigned short setAllEngOff; /* 0 = leave all engine state untouched.
 | ||||
|                                     1 = make sure they are off: 2D, Overlay, | ||||
|                                     video alpha, alpha, hardware cursors | ||||
|                                  */ | ||||
|     unsigned char resetMemory;   /* 0 = Do not reset the memory controller
 | ||||
|                                     1 = Reset the memory controller | ||||
|                                   */ | ||||
| 
 | ||||
|     /* More initialization parameter can be added if needed */ | ||||
| } | ||||
| initchip_param_t; | ||||
| 
 | ||||
| 
 | ||||
| logical_chip_type_t getChipType(void); | ||||
| unsigned int calcPllValue(unsigned int request,pll_value_t *pll); | ||||
| unsigned int calcPllValue2(unsigned int,pll_value_t *); | ||||
| unsigned int formatPllReg(pll_value_t *pPLL); | ||||
| void ddk750_set_mmio(volatile unsigned char *,unsigned short,char); | ||||
| unsigned int ddk750_getVMSize(void); | ||||
| int ddk750_initHw(initchip_param_t *); | ||||
| unsigned int getPllValue(clock_type_t clockType, pll_value_t *pPLL); | ||||
| unsigned int getChipClock(void); | ||||
| void setChipClock(unsigned int); | ||||
| void setMemoryClock(unsigned int frequency); | ||||
| void setMasterClock(unsigned int frequency); | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										318
									
								
								drivers/staging/sm750fb/ddk750_display.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								drivers/staging/sm750fb/ddk750_display.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,318 @@ | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_display.h" | ||||
| #include "ddk750_power.h" | ||||
| #include "ddk750_dvi.h" | ||||
| 
 | ||||
| #define primaryWaitVerticalSync(delay) waitNextVerticalSync(0,delay) | ||||
| 
 | ||||
| static void setDisplayControl(int ctrl,int dispState) | ||||
| { | ||||
| 	/* state != 0 means turn on both timing & plane en_bit */ | ||||
| 	unsigned long ulDisplayCtrlReg, ulReservedBits; | ||||
| 	int cnt; | ||||
| 
 | ||||
| 	cnt = 0; | ||||
| 
 | ||||
| 	/* Set the primary display control */ | ||||
| 	if (!ctrl) | ||||
| 	{ | ||||
| 		ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 		/* Turn on/off the Panel display control */ | ||||
| 		if (dispState) | ||||
| 		{ | ||||
| 			/* Timing should be enabled first before enabling the plane
 | ||||
| 			 * because changing at the same time does not guarantee that | ||||
| 			 * the plane will also enabled or disabled. | ||||
|      	     */ | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								PANEL_DISPLAY_CTRL, TIMING, ENABLE); | ||||
| 			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 
 | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								PANEL_DISPLAY_CTRL, PLANE, ENABLE); | ||||
| 
 | ||||
| 			/* Added some masks to mask out the reserved bits.
 | ||||
| 			 * Sometimes, the reserved bits are set/reset randomly when | ||||
| 			 * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register | ||||
| 			 * reserved bits are needed to be masked out. | ||||
| 			 */ | ||||
| 			ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | | ||||
| 				FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | | ||||
| 				FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE); | ||||
| 
 | ||||
| 			/* Somehow the register value on the plane is not set
 | ||||
| 			 * until a few delay. Need to write | ||||
| 			 * and read it a couple times | ||||
| 			 */ | ||||
| 			do | ||||
| 			{ | ||||
| 				cnt++; | ||||
| 				POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 			} while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != | ||||
| 					(ulDisplayCtrlReg & ~ulReservedBits)); | ||||
| 			printk("Set Panel Plane enbit:after tried %d times\n",cnt); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* When turning off, there is no rule on the programming
 | ||||
| 			 * sequence since whenever the clock is off, then it does not | ||||
| 			 * matter whether the plane is enabled or disabled. | ||||
| 			 * Note: Modifying the plane bit will take effect on the | ||||
| 			 * next vertical sync. Need to find out if it is necessary to | ||||
| 			 * wait for 1 vsync before modifying the timing enable bit. | ||||
| 			 * */ | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								PANEL_DISPLAY_CTRL, PLANE, DISABLE); | ||||
| 			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 
 | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								PANEL_DISPLAY_CTRL, TIMING, DISABLE); | ||||
| 			POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 	/* Set the secondary display control */ | ||||
| 	else | ||||
| 	{ | ||||
| 		ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL); | ||||
| 
 | ||||
| 		if (dispState) | ||||
| 		{ | ||||
| 			/* Timing should be enabled first before enabling the plane because changing at the
 | ||||
| 			   same time does not guarantee that the plane will also enabled or disabled. | ||||
| 			   */ | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								CRT_DISPLAY_CTRL, TIMING, ENABLE); | ||||
| 			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 
 | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								CRT_DISPLAY_CTRL, PLANE, ENABLE); | ||||
| 
 | ||||
| 			/* Added some masks to mask out the reserved bits.
 | ||||
| 			 * Sometimes, the reserved bits are set/reset randomly when | ||||
| 			 * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register | ||||
| 			 * reserved bits are needed to be masked out. | ||||
| 			 */ | ||||
| 
 | ||||
| 			ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | | ||||
| 				FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | | ||||
| 				FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | | ||||
| 				FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE); | ||||
| 
 | ||||
| 			do | ||||
| 			{ | ||||
| 				cnt++; | ||||
| 				POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 			} while((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) != | ||||
| 					(ulDisplayCtrlReg & ~ulReservedBits)); | ||||
| 				printk("Set Crt Plane enbit:after tried %d times\n",cnt); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* When turning off, there is no rule on the programming
 | ||||
| 			 * sequence since whenever the clock is off, then it does not | ||||
| 			 * matter whether the plane is enabled or disabled. | ||||
| 			 * Note: Modifying the plane bit will take effect on the next | ||||
| 			 * vertical sync. Need to find out if it is necessary to | ||||
| 			 * wait for 1 vsync before modifying the timing enable bit. | ||||
| 			 */ | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								CRT_DISPLAY_CTRL, PLANE, DISABLE); | ||||
| 			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 
 | ||||
| 			ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, | ||||
| 								CRT_DISPLAY_CTRL, TIMING, DISABLE); | ||||
| 			POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void waitNextVerticalSync(int ctrl,int delay) | ||||
| { | ||||
| 	unsigned int status; | ||||
| 	if(!ctrl){ | ||||
| 		/* primary controller */ | ||||
| 
 | ||||
|         /* Do not wait when the Primary PLL is off or display control is already off.
 | ||||
| 	           This will prevent the software to wait forever. */ | ||||
| 		if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) == | ||||
| 			 PANEL_PLL_CTRL_POWER_OFF) || | ||||
| 			(FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) == | ||||
| 			 PANEL_DISPLAY_CTRL_TIMING_DISABLE)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
|         while (delay-- > 0) | ||||
|         { | ||||
|             /* Wait for end of vsync. */ | ||||
|             do | ||||
|             { | ||||
|                 status = FIELD_GET(PEEK32(SYSTEM_CTRL), | ||||
|                                    SYSTEM_CTRL, | ||||
|                                    PANEL_VSYNC); | ||||
|             } | ||||
|             while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); | ||||
| 
 | ||||
|             /* Wait for start of vsync. */ | ||||
|             do | ||||
|             { | ||||
|                 status = FIELD_GET(PEEK32(SYSTEM_CTRL), | ||||
|                                    SYSTEM_CTRL, | ||||
|                                    PANEL_VSYNC); | ||||
|             } | ||||
|             while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE); | ||||
|         } | ||||
| 
 | ||||
| 	}else{ | ||||
| 
 | ||||
| 		/* Do not wait when the Primary PLL is off or display control is already off.
 | ||||
| 			   This will prevent the software to wait forever. */ | ||||
| 		if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) == | ||||
| 			 CRT_PLL_CTRL_POWER_OFF) || | ||||
| 			(FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) == | ||||
| 			 CRT_DISPLAY_CTRL_TIMING_DISABLE)) | ||||
| 		{ | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		while (delay-- > 0) | ||||
| 		{ | ||||
| 			/* Wait for end of vsync. */ | ||||
| 			do | ||||
| 			{ | ||||
| 				status = FIELD_GET(PEEK32(SYSTEM_CTRL), | ||||
| 								   SYSTEM_CTRL, | ||||
| 								   CRT_VSYNC); | ||||
| 			} | ||||
| 			while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE); | ||||
| 
 | ||||
| 			/* Wait for start of vsync. */ | ||||
| 			do | ||||
| 			{ | ||||
| 				status = FIELD_GET(PEEK32(SYSTEM_CTRL), | ||||
| 								   SYSTEM_CTRL, | ||||
| 								   CRT_VSYNC); | ||||
| 			} | ||||
| 			while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void swPanelPowerSequence_sm750le(int disp,int delay) | ||||
| { | ||||
| 	unsigned int reg; | ||||
| 	reg = PEEK32(DISPLAY_CONTROL_750LE); | ||||
| 	if(disp) | ||||
| 		reg |= 0xf; | ||||
| 	else | ||||
| 		reg &= ~0xf; | ||||
| 	POKE32(DISPLAY_CONTROL_750LE,reg); | ||||
| } | ||||
| 
 | ||||
| static void swPanelPowerSequence(int disp,int delay) | ||||
| { | ||||
| 	unsigned int reg; | ||||
| 
 | ||||
| 	/* disp should be 1 to open sequence */ | ||||
| 	reg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 	reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp); | ||||
| 	POKE32(PANEL_DISPLAY_CTRL,reg); | ||||
| 	primaryWaitVerticalSync(delay); | ||||
| 
 | ||||
| 
 | ||||
| 	reg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 	reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,DATA,disp); | ||||
| 	POKE32(PANEL_DISPLAY_CTRL,reg); | ||||
| 	primaryWaitVerticalSync(delay); | ||||
| 
 | ||||
| 	reg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 	reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,VBIASEN,disp); | ||||
| 	POKE32(PANEL_DISPLAY_CTRL,reg); | ||||
| 	primaryWaitVerticalSync(delay); | ||||
| 
 | ||||
| 
 | ||||
| 	reg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 	reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,FPEN,disp); | ||||
| 	POKE32(PANEL_DISPLAY_CTRL,reg); | ||||
| 	primaryWaitVerticalSync(delay); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void ddk750_setLogicalDispOut(disp_output_t output) | ||||
| { | ||||
| 	unsigned int reg; | ||||
| 	if(output & PNL_2_USAGE){ | ||||
| 		/* set panel path controller select */ | ||||
| 		reg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 		reg = FIELD_VALUE(reg,PANEL_DISPLAY_CTRL,SELECT,(output & PNL_2_MASK)>>PNL_2_OFFSET); | ||||
| 		POKE32(PANEL_DISPLAY_CTRL,reg); | ||||
| 	} | ||||
| 
 | ||||
| 	if(output & CRT_2_USAGE){ | ||||
| 		/* set crt path controller select */ | ||||
| 		reg = PEEK32(CRT_DISPLAY_CTRL); | ||||
| 		reg = FIELD_VALUE(reg,CRT_DISPLAY_CTRL,SELECT,(output & CRT_2_MASK)>>CRT_2_OFFSET); | ||||
| 		/*se blank off */ | ||||
| 		reg = FIELD_SET(reg,CRT_DISPLAY_CTRL,BLANK,OFF); | ||||
| 		POKE32(CRT_DISPLAY_CTRL,reg); | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	if(output & PRI_TP_USAGE){ | ||||
| 		/* set primary timing and plane en_bit */ | ||||
| 		setDisplayControl(0,(output&PRI_TP_MASK)>>PRI_TP_OFFSET); | ||||
| 	} | ||||
| 
 | ||||
| 	if(output & SEC_TP_USAGE){ | ||||
| 		/* set secondary timing and plane en_bit*/ | ||||
| 		setDisplayControl(1,(output&SEC_TP_MASK)>>SEC_TP_OFFSET); | ||||
| 	} | ||||
| 
 | ||||
| 	if(output & PNL_SEQ_USAGE){ | ||||
| 		/* set  panel sequence */ | ||||
| 		swPanelPowerSequence((output&PNL_SEQ_MASK)>>PNL_SEQ_OFFSET,4); | ||||
| 	} | ||||
| 
 | ||||
| 	if(output & DAC_USAGE) | ||||
| 		setDAC((output & DAC_MASK)>>DAC_OFFSET); | ||||
| 
 | ||||
| 	if(output & DPMS_USAGE) | ||||
| 		ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int ddk750_initDVIDisp() | ||||
| { | ||||
|     /* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
 | ||||
|        not zeroed, then set the failure flag. If it is zeroe, it might mean | ||||
|        that the system is in Dual CRT Monitor configuration. */ | ||||
| 
 | ||||
|     /* De-skew enabled with default 111b value.
 | ||||
|        This will fix some artifacts problem in some mode on board 2.2. | ||||
|        Somehow this fix does not affect board 2.1. | ||||
|      */ | ||||
|     if ((dviInit(1,  /* Select Rising Edge */ | ||||
|                 1,  /* Select 24-bit bus */ | ||||
|                 0,  /* Select Single Edge clock */ | ||||
|                 1,  /* Enable HSync as is */ | ||||
|                 1,  /* Enable VSync as is */ | ||||
|                 1,  /* Enable De-skew */ | ||||
|                 7,  /* Set the de-skew setting to maximum setup */ | ||||
|                 1,  /* Enable continuous Sync */ | ||||
|                 1,  /* Enable PLL Filter */ | ||||
|                 4   /* Use the recommended value for PLL Filter value */ | ||||
|         ) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000)) | ||||
|     { | ||||
|         return (-1); | ||||
|     } | ||||
| 
 | ||||
|     /* TODO: Initialize other display component */ | ||||
| 
 | ||||
|     /* Success */ | ||||
|     return 0; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										160
									
								
								drivers/staging/sm750fb/ddk750_display.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								drivers/staging/sm750fb/ddk750_display.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | ||||
| #ifndef DDK750_DISPLAY_H__ | ||||
| #define DDK750_DISPLAY_H__ | ||||
| 
 | ||||
| /* panel path select
 | ||||
| 	80000[29:28] | ||||
| */ | ||||
| 
 | ||||
| #define PNL_2_OFFSET 0 | ||||
| #define PNL_2_MASK (3 << PNL_2_OFFSET) | ||||
| #define PNL_2_USAGE	(PNL_2_MASK << 16) | ||||
| #define PNL_2_PRI 	((0 << PNL_2_OFFSET)|PNL_2_USAGE) | ||||
| #define PNL_2_SEC	((2 << PNL_2_OFFSET)|PNL_2_USAGE) | ||||
| 
 | ||||
| 
 | ||||
| /* primary timing & plane enable bit
 | ||||
| 	1: 80000[8] & 80000[2] on | ||||
| 	0: both off | ||||
| */ | ||||
| #define PRI_TP_OFFSET 4 | ||||
| #define PRI_TP_MASK (1 << PRI_TP_OFFSET) | ||||
| #define PRI_TP_USAGE (PRI_TP_MASK << 16) | ||||
| #define PRI_TP_ON ((0x1 << PRI_TP_OFFSET)|PRI_TP_USAGE) | ||||
| #define PRI_TP_OFF ((0x0 << PRI_TP_OFFSET)|PRI_TP_USAGE) | ||||
| 
 | ||||
| 
 | ||||
| /* panel sequency status
 | ||||
| 	80000[27:24] | ||||
| */ | ||||
| #define PNL_SEQ_OFFSET 6 | ||||
| #define PNL_SEQ_MASK (1 << PNL_SEQ_OFFSET) | ||||
| #define PNL_SEQ_USAGE (PNL_SEQ_MASK << 16) | ||||
| #define PNL_SEQ_ON ((1 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE) | ||||
| #define PNL_SEQ_OFF ((0 << PNL_SEQ_OFFSET)|PNL_SEQ_USAGE) | ||||
| 
 | ||||
| /* dual digital output
 | ||||
| 	80000[19] | ||||
| */ | ||||
| #define DUAL_TFT_OFFSET 8 | ||||
| #define DUAL_TFT_MASK (1 << DUAL_TFT_OFFSET) | ||||
| #define DUAL_TFT_USAGE (DUAL_TFT_MASK << 16) | ||||
| #define DUAL_TFT_ON ((1 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE) | ||||
| #define DUAL_TFT_OFF ((0 << DUAL_TFT_OFFSET)|DUAL_TFT_USAGE) | ||||
| 
 | ||||
| /* secondary timing & plane enable bit
 | ||||
| 	1:80200[8] & 80200[2] on | ||||
| 	0: both off | ||||
| */ | ||||
| #define SEC_TP_OFFSET 5 | ||||
| #define SEC_TP_MASK (1<< SEC_TP_OFFSET) | ||||
| #define SEC_TP_USAGE (SEC_TP_MASK << 16) | ||||
| #define SEC_TP_ON  ((0x1 << SEC_TP_OFFSET)|SEC_TP_USAGE) | ||||
| #define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET)|SEC_TP_USAGE) | ||||
| 
 | ||||
| /* crt path select
 | ||||
| 	80200[19:18] | ||||
| */ | ||||
| #define CRT_2_OFFSET 2 | ||||
| #define CRT_2_MASK (3 << CRT_2_OFFSET) | ||||
| #define CRT_2_USAGE (CRT_2_MASK << 16) | ||||
| #define CRT_2_PRI ((0x0 << CRT_2_OFFSET)|CRT_2_USAGE) | ||||
| #define CRT_2_SEC ((0x2 << CRT_2_OFFSET)|CRT_2_USAGE) | ||||
| 
 | ||||
| 
 | ||||
| /* DAC affect both DVI and DSUB
 | ||||
| 	4[20] | ||||
| */ | ||||
| #define DAC_OFFSET 7 | ||||
| #define DAC_MASK (1 << DAC_OFFSET) | ||||
| #define DAC_USAGE (DAC_MASK << 16) | ||||
| #define DAC_ON ((0x0<< DAC_OFFSET)|DAC_USAGE) | ||||
| #define DAC_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE) | ||||
| 
 | ||||
| /* DPMS only affect D-SUB head
 | ||||
| 	0[31:30] | ||||
| */ | ||||
| #define DPMS_OFFSET 9 | ||||
| #define DPMS_MASK (3 << DPMS_OFFSET) | ||||
| #define DPMS_USAGE (DPMS_MASK << 16) | ||||
| #define DPMS_OFF ((3 << DPMS_OFFSET)|DPMS_USAGE) | ||||
| #define DPMS_ON ((0 << DPMS_OFFSET)|DPMS_USAGE) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| 	LCD1 means panel path TFT1  & panel path DVI (so enable DAC) | ||||
| 	CRT means crt path DSUB | ||||
| */ | ||||
| #if 0 | ||||
| typedef enum _disp_output_t | ||||
| { | ||||
| 	NO_DISPLAY = DPMS_OFF, | ||||
| 
 | ||||
| 	LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON, | ||||
| 	LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON, | ||||
| 
 | ||||
| 	LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON|DPMS_OFF, | ||||
| 	LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON|DPMS_OFF, | ||||
| 
 | ||||
| 	DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DAC_ON, | ||||
| 	DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DAC_ON, | ||||
| 
 | ||||
| 	LCD1_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON| | ||||
| 					CRT_2_PRI|SEC_TP_OFF|DAC_ON, | ||||
| 
 | ||||
| 	LCD1_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON| | ||||
| 					CRT_2_SEC|PRI_TP_OFF|DAC_ON, | ||||
| 
 | ||||
| 	/* LCD1 show primary and DSUB show secondary */ | ||||
| 	LCD1_DSUB_DUAL = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON| | ||||
| 					 CRT_2_SEC|SEC_TP_ON|DAC_ON, | ||||
| 
 | ||||
| 	/* LCD1 show secondary and DSUB show primary */ | ||||
| 	LCD1_DSUB_DUAL_SWAP = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON| | ||||
| 							CRT_2_PRI|PRI_TP_ON|DAC_ON, | ||||
| 
 | ||||
| 	LCD1_LCD2_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON| | ||||
| 					CRT_2_PRI|SEC_TP_OFF|DPMS_OFF|DUAL_TFT_ON, | ||||
| 
 | ||||
| 	LCD1_LCD2_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON| | ||||
| 					CRT_2_SEC|PRI_TP_OFF|DPMS_OFF|DUAL_TFT_ON, | ||||
| 
 | ||||
| 	LCD1_LCD2_DSUB_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON| | ||||
| 						CRT_2_PRI|SEC_TP_OFF|DPMS_ON|DUAL_TFT_ON, | ||||
| 
 | ||||
| 	LCD1_LCD2_DSUB_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON| | ||||
| 						CRT_2_SEC|PRI_TP_OFF|DPMS_ON|DUAL_TFT_ON, | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| disp_output_t; | ||||
| #else | ||||
| typedef enum _disp_output_t{ | ||||
| 	do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON, | ||||
| 	do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON, | ||||
| #if 0 | ||||
| 	do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON, | ||||
| 	do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON, | ||||
| #else | ||||
| 	do_LCD2_PRI = CRT_2_PRI|PRI_TP_ON|DUAL_TFT_ON, | ||||
| 	do_LCD2_SEC = CRT_2_SEC|SEC_TP_ON|DUAL_TFT_ON, | ||||
| #endif | ||||
| 	/*
 | ||||
| 	do_DSUB_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, | ||||
| 	do_DSUB_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, | ||||
| 	*/ | ||||
| #if 0 | ||||
| 	do_CRT_PRI = CRT_2_PRI|PRI_TP_ON, | ||||
| 	do_CRT_SEC = CRT_2_SEC|SEC_TP_ON, | ||||
| #else | ||||
| 	do_CRT_PRI = CRT_2_PRI|PRI_TP_ON|DPMS_ON|DAC_ON, | ||||
| 	do_CRT_SEC = CRT_2_SEC|SEC_TP_ON|DPMS_ON|DAC_ON, | ||||
| #endif | ||||
| } | ||||
| disp_output_t; | ||||
| #endif | ||||
| 
 | ||||
| void ddk750_setLogicalDispOut(disp_output_t); | ||||
| int ddk750_initDVIDisp(void); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										99
									
								
								drivers/staging/sm750fb/ddk750_dvi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								drivers/staging/sm750fb/ddk750_dvi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| #define USE_DVICHIP  | ||||
| #ifdef USE_DVICHIP | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_dvi.h" | ||||
| #include "ddk750_sii164.h" | ||||
| 
 | ||||
| 
 | ||||
| /* This global variable contains all the supported driver and its corresponding
 | ||||
|    function API. Please set the function pointer to NULL whenever the function | ||||
|    is not supported. */ | ||||
| static dvi_ctrl_device_t g_dcftSupportedDviController[] = | ||||
| { | ||||
| #ifdef DVI_CTRL_SII164 | ||||
|     { | ||||
|         .pfnInit = sii164InitChip, | ||||
|         .pfnGetVendorId = sii164GetVendorID, | ||||
|         .pfnGetDeviceId = sii164GetDeviceID, | ||||
| #ifdef SII164_FULL_FUNCTIONS | ||||
|         .pfnResetChip = sii164ResetChip, | ||||
|         .pfnGetChipString = sii164GetChipString, | ||||
|         .pfnSetPower = sii164SetPower, | ||||
|         .pfnEnableHotPlugDetection = sii164EnableHotPlugDetection, | ||||
|         .pfnIsConnected = sii164IsConnected, | ||||
|         .pfnCheckInterrupt = sii164CheckInterrupt, | ||||
|         .pfnClearInterrupt = sii164ClearInterrupt, | ||||
| #endif | ||||
|     }, | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| int dviInit( | ||||
|     unsigned char edgeSelect, | ||||
|     unsigned char busSelect, | ||||
|     unsigned char dualEdgeClkSelect, | ||||
|     unsigned char hsyncEnable, | ||||
|     unsigned char vsyncEnable, | ||||
|     unsigned char deskewEnable, | ||||
|     unsigned char deskewSetting, | ||||
|     unsigned char continuousSyncEnable, | ||||
|     unsigned char pllFilterEnable, | ||||
|     unsigned char pllFilterValue | ||||
| 			) | ||||
| { | ||||
| 	dvi_ctrl_device_t *pCurrentDviCtrl; | ||||
| 	pCurrentDviCtrl = g_dcftSupportedDviController; | ||||
| 	if(pCurrentDviCtrl->pfnInit != NULL) | ||||
| 	{ | ||||
| 		return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, dualEdgeClkSelect, hsyncEnable, | ||||
|                               vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable, | ||||
|                               pllFilterEnable, pllFilterValue); | ||||
| 	} | ||||
| 	return -1;//error
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  dviGetVendorID | ||||
|  *      This function gets the vendor ID of the DVI controller chip. | ||||
|  * | ||||
|  *  Output: | ||||
|  *      Vendor ID | ||||
|  */ | ||||
| unsigned short dviGetVendorID() | ||||
| { | ||||
|     dvi_ctrl_device_t *pCurrentDviCtrl; | ||||
| 
 | ||||
|     //pCurrentDviCtrl = getDviCtrl();
 | ||||
|     pCurrentDviCtrl = g_dcftSupportedDviController; | ||||
|     if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0) | ||||
|         return pCurrentDviCtrl->pfnGetVendorId(); | ||||
| 
 | ||||
|     return 0x0000; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  dviGetDeviceID | ||||
|  *      This function gets the device ID of the DVI controller chip. | ||||
|  * | ||||
|  *  Output: | ||||
|  *      Device ID | ||||
|  */ | ||||
| unsigned short dviGetDeviceID() | ||||
| { | ||||
|     dvi_ctrl_device_t *pCurrentDviCtrl; | ||||
| 
 | ||||
| //    pCurrentDviCtrl = getDviCtrl();
 | ||||
| 	pCurrentDviCtrl = g_dcftSupportedDviController; | ||||
|     if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0) | ||||
|         return pCurrentDviCtrl->pfnGetDeviceId(); | ||||
| 
 | ||||
|     return 0x0000; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										67
									
								
								drivers/staging/sm750fb/ddk750_dvi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								drivers/staging/sm750fb/ddk750_dvi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| #ifndef DDK750_DVI_H__ | ||||
| #define DDK750_DVI_H__ | ||||
| 
 | ||||
| /* dvi chip stuffs structros */ | ||||
| 
 | ||||
| typedef long (*PFN_DVICTRL_INIT)( | ||||
|     unsigned char edgeSelect, | ||||
|     unsigned char busSelect, | ||||
|     unsigned char dualEdgeClkSelect, | ||||
|     unsigned char hsyncEnable, | ||||
|     unsigned char vsyncEnable, | ||||
|     unsigned char deskewEnable, | ||||
|     unsigned char deskewSetting, | ||||
|     unsigned char continuousSyncEnable, | ||||
|     unsigned char pllFilterEnable, | ||||
|     unsigned char pllFilterValue); | ||||
| typedef void (*PFN_DVICTRL_RESETCHIP)(void); | ||||
| typedef char* (*PFN_DVICTRL_GETCHIPSTRING)(void); | ||||
| typedef unsigned short (*PFN_DVICTRL_GETVENDORID)(void); | ||||
| typedef unsigned short (*PFN_DVICTRL_GETDEVICEID)(void); | ||||
| typedef void (*PFN_DVICTRL_SETPOWER)(unsigned char powerUp); | ||||
| typedef void (*PFN_DVICTRL_HOTPLUGDETECTION)(unsigned char enableHotPlug); | ||||
| typedef unsigned char (*PFN_DVICTRL_ISCONNECTED)(void); | ||||
| typedef unsigned char (*PFN_DVICTRL_CHECKINTERRUPT)(void); | ||||
| typedef void (*PFN_DVICTRL_CLEARINTERRUPT)(void); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Structure to hold all the function pointer to the DVI Controller. */ | ||||
| typedef struct _dvi_ctrl_device_t | ||||
| { | ||||
|     PFN_DVICTRL_INIT                pfnInit; | ||||
|     PFN_DVICTRL_RESETCHIP           pfnResetChip; | ||||
|     PFN_DVICTRL_GETCHIPSTRING       pfnGetChipString; | ||||
|     PFN_DVICTRL_GETVENDORID         pfnGetVendorId; | ||||
|     PFN_DVICTRL_GETDEVICEID         pfnGetDeviceId; | ||||
|     PFN_DVICTRL_SETPOWER            pfnSetPower; | ||||
|     PFN_DVICTRL_HOTPLUGDETECTION    pfnEnableHotPlugDetection; | ||||
|     PFN_DVICTRL_ISCONNECTED         pfnIsConnected; | ||||
|     PFN_DVICTRL_CHECKINTERRUPT      pfnCheckInterrupt; | ||||
|     PFN_DVICTRL_CLEARINTERRUPT      pfnClearInterrupt; | ||||
| } dvi_ctrl_device_t; | ||||
| #define DVI_CTRL_SII164 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* dvi functions prototype */ | ||||
| int dviInit( | ||||
|     unsigned char edgeSelect, | ||||
|     unsigned char busSelect, | ||||
|     unsigned char dualEdgeClkSelect, | ||||
|     unsigned char hsyncEnable, | ||||
|     unsigned char vsyncEnable, | ||||
|     unsigned char deskewEnable, | ||||
|     unsigned char deskewSetting, | ||||
|     unsigned char continuousSyncEnable, | ||||
|     unsigned char pllFilterEnable, | ||||
|     unsigned char pllFilterValue | ||||
| ); | ||||
| 
 | ||||
| unsigned short dviGetVendorID(void); | ||||
| unsigned short dviGetDeviceID(void); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
							
								
								
									
										19
									
								
								drivers/staging/sm750fb/ddk750_help.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								drivers/staging/sm750fb/ddk750_help.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| //#include "ddk750_reg.h"
 | ||||
| //#include "ddk750_chip.h"
 | ||||
| #include "ddk750_help.h" | ||||
| 
 | ||||
| volatile unsigned char __iomem * mmio750 = NULL; | ||||
| char revId750 = 0; | ||||
| unsigned short devId750 = 0; | ||||
| 
 | ||||
| /* after driver mapped io registers, use this function first */ | ||||
| void ddk750_set_mmio(volatile unsigned char * addr,unsigned short devId,char revId) | ||||
| { | ||||
| 	mmio750 = addr; | ||||
| 	devId750 = devId; | ||||
| 	revId750 = revId; | ||||
| 	if(revId == 0xfe) | ||||
| 		printk("found sm750le\n"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										29
									
								
								drivers/staging/sm750fb/ddk750_help.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								drivers/staging/sm750fb/ddk750_help.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| #ifndef DDK750_HELP_H__ | ||||
| #define DDK750_HELP_H__ | ||||
| #include "ddk750_chip.h" | ||||
| #ifndef USE_INTERNAL_REGISTER_ACCESS | ||||
| 
 | ||||
| #include <linux/ioport.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include "sm750_help.h" | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| /* if 718 big endian turned on,be aware that don't use this driver for general use,only for ppc big-endian */ | ||||
| #warning "big endian on target cpu and enable nature big endian support of 718 capability !" | ||||
| #define PEEK32(addr)  			__raw_readl((void __iomem *)(mmio750)+(addr)) | ||||
| #define POKE32(addr,data) 		__raw_writel((data),(void __iomem*)(mmio750)+(addr)) | ||||
| #else /* software control endianess */ | ||||
| #define PEEK32(addr) readl((addr)+mmio750) | ||||
| #define POKE32(addr,data) writel((data),(addr)+mmio750) | ||||
| #endif | ||||
| 
 | ||||
| extern volatile unsigned  char __iomem * mmio750; | ||||
| extern char revId750; | ||||
| extern unsigned short devId750; | ||||
| #else | ||||
| /* implement if you want use it*/ | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										271
									
								
								drivers/staging/sm750fb/ddk750_hwi2c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								drivers/staging/sm750fb/ddk750_hwi2c.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,271 @@ | ||||
| #define USE_HW_I2C | ||||
| #ifdef USE_HW_I2C | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_hwi2c.h" | ||||
| #include "ddk750_power.h" | ||||
| 
 | ||||
| #define MAX_HWI2C_FIFO                  16 | ||||
| #define HWI2C_WAIT_TIMEOUT              0xF0000 | ||||
| 
 | ||||
| 
 | ||||
| int hwI2CInit( | ||||
|     unsigned char busSpeedMode | ||||
| ) | ||||
| { | ||||
|     unsigned int value; | ||||
| 
 | ||||
|     /* Enable GPIO 30 & 31 as IIC clock & data */ | ||||
| 	value = PEEK32(GPIO_MUX); | ||||
| 
 | ||||
|     value = FIELD_SET(value, GPIO_MUX, 30, I2C) | | ||||
| 			FIELD_SET(0, GPIO_MUX, 31, I2C); | ||||
| 	POKE32(GPIO_MUX, value); | ||||
| 
 | ||||
|     /* Enable Hardware I2C power.
 | ||||
|        TODO: Check if we need to enable GPIO power? | ||||
|      */ | ||||
|     enableI2C(1); | ||||
| 
 | ||||
|     /* Enable the I2C Controller and set the bus speed mode */ | ||||
|     value = PEEK32(I2C_CTRL); | ||||
|     if (busSpeedMode == 0) | ||||
|         value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD); | ||||
|     else | ||||
|         value = FIELD_SET(value, I2C_CTRL, MODE, FAST); | ||||
|     value = FIELD_SET(value, I2C_CTRL, EN, ENABLE); | ||||
|     POKE32(I2C_CTRL, value); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void hwI2CClose(void) | ||||
| { | ||||
|     unsigned int value; | ||||
| 
 | ||||
|     /* Disable I2C controller */ | ||||
|     value = PEEK32(I2C_CTRL); | ||||
|     value = FIELD_SET(value, I2C_CTRL, EN, DISABLE); | ||||
|     POKE32(I2C_CTRL, value); | ||||
| 
 | ||||
|     /* Disable I2C Power */ | ||||
|     enableI2C(0); | ||||
| 
 | ||||
|     /* Set GPIO 30 & 31 back as GPIO pins */ | ||||
|     value = PEEK32(GPIO_MUX); | ||||
|     value = FIELD_SET(value, GPIO_MUX, 30, GPIO); | ||||
|     value = FIELD_SET(value, GPIO_MUX, 31, GPIO); | ||||
|     POKE32(GPIO_MUX, value); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| long hwI2CWaitTXDone(void) | ||||
| { | ||||
|     unsigned int timeout; | ||||
| 
 | ||||
|     /* Wait until the transfer is completed. */ | ||||
|     timeout = HWI2C_WAIT_TIMEOUT; | ||||
| 	while ((FIELD_GET(PEEK32(I2C_STATUS), I2C_STATUS, TX) != I2C_STATUS_TX_COMPLETED) && | ||||
|            (timeout != 0)) | ||||
| 		timeout--; | ||||
| 
 | ||||
| 	if (timeout == 0) | ||||
| 	    return (-1); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function writes data to the i2c slave device registers. | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address | ||||
|  *      length          - Total number of bytes to be written to the device | ||||
|  *      pBuffer         - The buffer that contains the data to be written to the | ||||
|  *                     i2c device. | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      Total number of bytes those are actually written. | ||||
|  */ | ||||
| unsigned int hwI2CWriteData( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned int length, | ||||
|     unsigned char *pBuffer | ||||
| ) | ||||
| { | ||||
|     unsigned char count, i; | ||||
|     unsigned int totalBytes = 0; | ||||
| 
 | ||||
|     /* Set the Device Address */ | ||||
|     POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01); | ||||
| 
 | ||||
|     /* Write data.
 | ||||
|      * Note: | ||||
|      *      Only 16 byte can be accessed per i2c start instruction. | ||||
|      */ | ||||
|     do | ||||
|     { | ||||
|         /* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */ | ||||
|         POKE32(I2C_RESET, 0); | ||||
| 
 | ||||
|         /* Set the number of bytes to be written */ | ||||
|         if (length < MAX_HWI2C_FIFO) | ||||
|             count = length - 1; | ||||
|         else | ||||
|             count = MAX_HWI2C_FIFO - 1; | ||||
|         POKE32(I2C_BYTE_COUNT, count); | ||||
| 
 | ||||
|         /* Move the data to the I2C data register */ | ||||
| 	    for (i = 0; i <= count; i++) | ||||
|             POKE32(I2C_DATA0 + i, *pBuffer++); | ||||
| 
 | ||||
|         /* Start the I2C */ | ||||
|         POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START)); | ||||
| 
 | ||||
|         /* Wait until the transfer is completed. */ | ||||
|         if (hwI2CWaitTXDone() != 0) | ||||
|             break; | ||||
| 
 | ||||
|         /* Substract length */ | ||||
|         length -= (count + 1); | ||||
| 
 | ||||
|         /* Total byte written */ | ||||
|         totalBytes += (count + 1); | ||||
| 
 | ||||
|     } while (length > 0); | ||||
| 
 | ||||
|     return totalBytes; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function reads data from the slave device and stores them | ||||
|  *  in the given buffer | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address | ||||
|  *      length          - Total number of bytes to be read | ||||
|  *      pBuffer         - Pointer to a buffer to be filled with the data read | ||||
|  *                     from the slave device. It has to be the same size as the | ||||
|  *                     length to make sure that it can keep all the data read. | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      Total number of actual bytes read from the slave device | ||||
|  */ | ||||
| unsigned int hwI2CReadData( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned int length, | ||||
|     unsigned char *pBuffer | ||||
| ) | ||||
| { | ||||
|     unsigned char count, i; | ||||
|     unsigned int totalBytes = 0; | ||||
| 
 | ||||
|     /* Set the Device Address */ | ||||
|     POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01); | ||||
| 
 | ||||
|     /* Read data and save them to the buffer.
 | ||||
|      * Note: | ||||
|      *      Only 16 byte can be accessed per i2c start instruction. | ||||
|      */ | ||||
|     do | ||||
|     { | ||||
|         /* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */ | ||||
|         POKE32(I2C_RESET, 0); | ||||
| 
 | ||||
|         /* Set the number of bytes to be read */ | ||||
|         if (length <= MAX_HWI2C_FIFO) | ||||
|             count = length - 1; | ||||
|         else | ||||
|             count = MAX_HWI2C_FIFO - 1; | ||||
|         POKE32(I2C_BYTE_COUNT, count); | ||||
| 
 | ||||
|         /* Start the I2C */ | ||||
|         POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START)); | ||||
| 
 | ||||
|         /* Wait until transaction done. */ | ||||
|         if (hwI2CWaitTXDone() != 0) | ||||
|             break; | ||||
| 
 | ||||
|         /* Save the data to the given buffer */ | ||||
|         for (i = 0; i <= count; i++) | ||||
| 		    *pBuffer++ = PEEK32(I2C_DATA0 + i); | ||||
| 
 | ||||
|         /* Substract length by 16 */ | ||||
|         length -= (count + 1); | ||||
| 
 | ||||
|         /* Number of bytes read. */ | ||||
|         totalBytes += (count + 1); | ||||
| 
 | ||||
|     } while (length > 0); | ||||
| 
 | ||||
|     return totalBytes; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function reads the slave device's register | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address which register | ||||
|  *                        to be read from | ||||
|  *      registerIndex   - Slave device's register to be read | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      Register value | ||||
|  */ | ||||
| unsigned char hwI2CReadReg( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned char registerIndex | ||||
| ) | ||||
| { | ||||
|     unsigned char value = (0xFF); | ||||
| 
 | ||||
|     if (hwI2CWriteData(deviceAddress, 1, ®isterIndex) == 1) | ||||
|         hwI2CReadData(deviceAddress, 1, &value); | ||||
| 
 | ||||
|     return value; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function writes a value to the slave device's register | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address which register | ||||
|  *                        to be written | ||||
|  *      registerIndex   - Slave device's register to be written | ||||
|  *      data            - Data to be written to the register | ||||
|  * | ||||
|  *  Result: | ||||
|  *          0   - Success | ||||
|  *         -1   - Fail | ||||
|  */ | ||||
| int hwI2CWriteReg( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned char registerIndex, | ||||
|     unsigned char data | ||||
| ) | ||||
| { | ||||
|     unsigned char value[2]; | ||||
| 
 | ||||
|     value[0] = registerIndex; | ||||
|     value[1] = data; | ||||
|     if (hwI2CWriteData(deviceAddress, 2, value) == 2) | ||||
|         return 0; | ||||
| 
 | ||||
|     return (-1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										10
									
								
								drivers/staging/sm750fb/ddk750_hwi2c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								drivers/staging/sm750fb/ddk750_hwi2c.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #ifndef DDK750_HWI2C_H__ | ||||
| #define DDK750_HWI2C_H__ | ||||
| 
 | ||||
| /* hwi2c functions */ | ||||
| int hwI2CInit(unsigned char busSpeedMode); | ||||
| void hwI2CClose(void); | ||||
| 
 | ||||
| unsigned char hwI2CReadReg(unsigned char deviceAddress,unsigned char registerIndex); | ||||
| int hwI2CWriteReg(unsigned char deviceAddress,unsigned char registerIndex,unsigned char data); | ||||
| #endif | ||||
							
								
								
									
										205
									
								
								drivers/staging/sm750fb/ddk750_mode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								drivers/staging/sm750fb/ddk750_mode.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,205 @@ | ||||
| 
 | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_mode.h" | ||||
| #include "ddk750_chip.h" | ||||
| 
 | ||||
| /*
 | ||||
| 	SM750LE only: | ||||
|     This function takes care extra registers and bit fields required to set | ||||
|     up a mode in SM750LE | ||||
| 
 | ||||
| 	Explanation about Display Control register: | ||||
|     HW only supports 7 predefined pixel clocks, and clock select is | ||||
|     in bit 29:27 of	Display Control register. | ||||
| */ | ||||
| static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, unsigned long dispControl) | ||||
| { | ||||
| 	unsigned long x, y; | ||||
| 
 | ||||
| 	x = pModeParam->horizontal_display_end; | ||||
| 	y = pModeParam->vertical_display_end; | ||||
| 
 | ||||
|     /* SM750LE has to set up the top-left and bottom-right
 | ||||
|        registers as well. | ||||
|        Note that normal SM750/SM718 only use those two register for | ||||
|        auto-centering mode. | ||||
|     */ | ||||
|     POKE32(CRT_AUTO_CENTERING_TL, | ||||
|       FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0) | ||||
|     | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0)); | ||||
| 
 | ||||
|     POKE32(CRT_AUTO_CENTERING_BR, | ||||
|       FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1) | ||||
|     | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1)); | ||||
| 
 | ||||
|     /* Assume common fields in dispControl have been properly set before
 | ||||
|        calling this function. | ||||
|        This function only sets the extra fields in dispControl. | ||||
|     */ | ||||
| 
 | ||||
| 	/* Clear bit 29:27 of display control register */ | ||||
|     dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK); | ||||
| 
 | ||||
| 	/* Set bit 29:27 of display control register for the right clock */ | ||||
| 	/* Note that SM750LE only need to supported 7 resoluitons. */ | ||||
| 	if ( x == 800 && y == 600 ) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41); | ||||
| 	else if (x == 1024 && y == 768) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65); | ||||
| 	else if (x == 1152 && y == 864) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80); | ||||
| 	else if (x == 1280 && y == 768) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80); | ||||
| 	else if (x == 1280 && y == 720) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74); | ||||
| 	else if (x == 1280 && y == 960) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108); | ||||
| 	else if (x == 1280 && y == 1024) | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108); | ||||
| 	else /* default to VGA clock */ | ||||
|     	dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25); | ||||
| 
 | ||||
| 	/* Set bit 25:24 of display controller */ | ||||
|     dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT); | ||||
|     dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT); | ||||
| 
 | ||||
|     /* Set bit 14 of display controller */ | ||||
|     dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW); | ||||
| 
 | ||||
|     POKE32(CRT_DISPLAY_CTRL, dispControl); | ||||
| 
 | ||||
| 	return dispControl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* only timing related registers will be  programed */ | ||||
| static int programModeRegisters(mode_parameter_t * pModeParam,pll_value_t * pll) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	int cnt = 0; | ||||
| 	unsigned int ulTmpValue,ulReg; | ||||
| 	if(pll->clockType == SECONDARY_PLL) | ||||
| 	{ | ||||
| 		/* programe secondary pixel clock */ | ||||
| 		POKE32(CRT_PLL_CTRL,formatPllReg(pll)); | ||||
|         POKE32(CRT_HORIZONTAL_TOTAL, | ||||
|               FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1) | ||||
|             | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1)); | ||||
| 
 | ||||
|         POKE32(CRT_HORIZONTAL_SYNC, | ||||
|               FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width) | ||||
|             | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1)); | ||||
| 
 | ||||
|         POKE32(CRT_VERTICAL_TOTAL, | ||||
|               FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1) | ||||
|             | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1)); | ||||
| 
 | ||||
|         POKE32(CRT_VERTICAL_SYNC, | ||||
|               FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | ||||
|             | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); | ||||
| 
 | ||||
| 
 | ||||
| 		ulTmpValue = FIELD_VALUE(0,CRT_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)| | ||||
| 					  FIELD_VALUE(0,CRT_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)| | ||||
| 					  FIELD_SET(0,CRT_DISPLAY_CTRL,TIMING,ENABLE)| | ||||
| 					  FIELD_SET(0,CRT_DISPLAY_CTRL,PLANE,ENABLE); | ||||
| 
 | ||||
| 
 | ||||
| 		if(getChipType() == SM750LE){ | ||||
| 			displayControlAdjust_SM750LE(pModeParam,ulTmpValue); | ||||
| 		}else{ | ||||
| 			ulReg = PEEK32(CRT_DISPLAY_CTRL) | ||||
| 					& FIELD_CLEAR(CRT_DISPLAY_CTRL,VSYNC_PHASE) | ||||
| 					& FIELD_CLEAR(CRT_DISPLAY_CTRL,HSYNC_PHASE) | ||||
| 					& FIELD_CLEAR(CRT_DISPLAY_CTRL,TIMING) | ||||
| 					& FIELD_CLEAR(CRT_DISPLAY_CTRL,PLANE); | ||||
| 
 | ||||
| 			 POKE32(CRT_DISPLAY_CTRL,ulTmpValue|ulReg); | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 	else if(pll->clockType == PRIMARY_PLL) | ||||
| 	{ | ||||
| 		unsigned int ulReservedBits; | ||||
| 		POKE32(PANEL_PLL_CTRL,formatPllReg(pll)); | ||||
| 
 | ||||
|         POKE32(PANEL_HORIZONTAL_TOTAL, | ||||
|               FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1) | ||||
|             | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1)); | ||||
| 
 | ||||
|         POKE32(PANEL_HORIZONTAL_SYNC, | ||||
|               FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width) | ||||
|             | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1)); | ||||
| 
 | ||||
|         POKE32(PANEL_VERTICAL_TOTAL, | ||||
|               FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1) | ||||
|             | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1)); | ||||
| 
 | ||||
|         POKE32(PANEL_VERTICAL_SYNC, | ||||
|               FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | ||||
|             | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); | ||||
| 
 | ||||
| 		ulTmpValue = FIELD_VALUE(0,PANEL_DISPLAY_CTRL,VSYNC_PHASE,pModeParam->vertical_sync_polarity)| | ||||
| 					FIELD_VALUE(0,PANEL_DISPLAY_CTRL,HSYNC_PHASE,pModeParam->horizontal_sync_polarity)| | ||||
| 					FIELD_VALUE(0,PANEL_DISPLAY_CTRL,CLOCK_PHASE,pModeParam->clock_phase_polarity)| | ||||
| 					FIELD_SET(0,PANEL_DISPLAY_CTRL,TIMING,ENABLE)| | ||||
| 					FIELD_SET(0,PANEL_DISPLAY_CTRL,PLANE,ENABLE); | ||||
| 
 | ||||
|         ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | | ||||
|                          FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | | ||||
|                          FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)| | ||||
|                          FIELD_SET(0,PANEL_DISPLAY_CTRL,VSYNC,ACTIVE_LOW); | ||||
| 
 | ||||
|         ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) | ||||
|               & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE) | ||||
|               & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE) | ||||
|               & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE) | ||||
|               & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING) | ||||
|               & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE); | ||||
| 
 | ||||
| 
 | ||||
| 		/* May a hardware bug or just my test chip (not confirmed).
 | ||||
| 		* PANEL_DISPLAY_CTRL register seems requiring few writes | ||||
| 		* before a value can be succesfully written in. | ||||
| 		* Added some masks to mask out the reserved bits. | ||||
| 		* Note: This problem happens by design. The hardware will wait for the | ||||
| 		*       next vertical sync to turn on/off the plane. | ||||
| 		*/ | ||||
| 
 | ||||
| 		POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg); | ||||
| #if 1 | ||||
| 		while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) | ||||
| 		{ | ||||
| 			cnt++; | ||||
| 			if(cnt > 1000) | ||||
| 				break; | ||||
| 			POKE32(PANEL_DISPLAY_CTRL,ulTmpValue|ulReg); | ||||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| 	else{ | ||||
| 		ret = -1; | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int ddk750_setModeTiming(mode_parameter_t * parm,clock_type_t clock) | ||||
| { | ||||
| 	pll_value_t pll; | ||||
| 	unsigned int uiActualPixelClk; | ||||
| 	pll.inputFreq = DEFAULT_INPUT_CLOCK; | ||||
| 	pll.clockType = clock; | ||||
| 
 | ||||
| 	uiActualPixelClk = calcPllValue(parm->pixel_clock,&pll); | ||||
| 	if(getChipType() == SM750LE){ | ||||
| 		/* set graphic mode via IO method */ | ||||
| 		outb_p(0x88,0x3d4); | ||||
| 		outb_p(0x06,0x3d5); | ||||
| 	} | ||||
| 	programModeRegisters(parm,&pll); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										43
									
								
								drivers/staging/sm750fb/ddk750_mode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								drivers/staging/sm750fb/ddk750_mode.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| #ifndef DDK750_MODE_H__ | ||||
| #define DDK750_MODE_H__ | ||||
| 
 | ||||
| #include "ddk750_chip.h" | ||||
| 
 | ||||
| typedef enum _spolarity_t | ||||
| { | ||||
|     POS = 0, /* positive */ | ||||
|     NEG, /* negative */ | ||||
| } | ||||
| spolarity_t; | ||||
| 
 | ||||
| 
 | ||||
| typedef struct _mode_parameter_t | ||||
| { | ||||
|     /* Horizontal timing. */ | ||||
|     unsigned long horizontal_total; | ||||
|     unsigned long horizontal_display_end; | ||||
|     unsigned long horizontal_sync_start; | ||||
|     unsigned long horizontal_sync_width; | ||||
|     spolarity_t horizontal_sync_polarity; | ||||
| 
 | ||||
|     /* Vertical timing. */ | ||||
|     unsigned long vertical_total; | ||||
|     unsigned long vertical_display_end; | ||||
|     unsigned long vertical_sync_start; | ||||
|     unsigned long vertical_sync_height; | ||||
|     spolarity_t vertical_sync_polarity; | ||||
| 
 | ||||
|     /* Refresh timing. */ | ||||
|     unsigned long pixel_clock; | ||||
|     unsigned long horizontal_frequency; | ||||
|     unsigned long vertical_frequency; | ||||
| 
 | ||||
|     /* Clock Phase. This clock phase only applies to Panel. */ | ||||
|     spolarity_t clock_phase_polarity; | ||||
| } | ||||
| mode_parameter_t; | ||||
| 
 | ||||
| int ddk750_setModeTiming(mode_parameter_t *,clock_type_t); | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										239
									
								
								drivers/staging/sm750fb/ddk750_power.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								drivers/staging/sm750fb/ddk750_power.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,239 @@ | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_power.h" | ||||
| 
 | ||||
| void ddk750_setDPMS(DPMS_t state) | ||||
| { | ||||
| 	unsigned int value; | ||||
| 	if(getChipType() == SM750LE){ | ||||
| 		value = PEEK32(CRT_DISPLAY_CTRL); | ||||
| 		POKE32(CRT_DISPLAY_CTRL,FIELD_VALUE(value,CRT_DISPLAY_CTRL,DPMS,state)); | ||||
| 	}else{ | ||||
| 		value = PEEK32(SYSTEM_CTRL); | ||||
| 		value= FIELD_VALUE(value,SYSTEM_CTRL,DPMS,state); | ||||
| 		POKE32(SYSTEM_CTRL, value); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| unsigned int getPowerMode() | ||||
| { | ||||
| 	if(getChipType() == SM750LE) | ||||
| 		return 0; | ||||
|     return (FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * SM50x can operate in one of three modes: 0, 1 or Sleep. | ||||
|  * On hardware reset, power mode 0 is default. | ||||
|  */ | ||||
| void setPowerMode(unsigned int powerMode) | ||||
| { | ||||
|     unsigned int control_value = 0; | ||||
| 
 | ||||
|     control_value = PEEK32(POWER_MODE_CTRL); | ||||
| 
 | ||||
| 	if(getChipType() == SM750LE) | ||||
| 		return; | ||||
| 
 | ||||
|     switch (powerMode) | ||||
|     { | ||||
|         case POWER_MODE_CTRL_MODE_MODE0: | ||||
|             control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0); | ||||
|             break; | ||||
| 
 | ||||
|         case POWER_MODE_CTRL_MODE_MODE1: | ||||
|             control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE1); | ||||
|             break; | ||||
| 
 | ||||
|         case POWER_MODE_CTRL_MODE_SLEEP: | ||||
|             control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, SLEEP); | ||||
|             break; | ||||
| 
 | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     /* Set up other fields in Power Control Register */ | ||||
|     if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) | ||||
|     { | ||||
|         control_value = | ||||
| #ifdef VALIDATION_CHIP | ||||
|             FIELD_SET(  control_value, POWER_MODE_CTRL, 336CLK, OFF) | | ||||
| #endif | ||||
|             FIELD_SET(  control_value, POWER_MODE_CTRL, OSC_INPUT,  OFF); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         control_value = | ||||
| #ifdef VALIDATION_CHIP | ||||
|             FIELD_SET(  control_value, POWER_MODE_CTRL, 336CLK, ON) | | ||||
| #endif | ||||
|             FIELD_SET(  control_value, POWER_MODE_CTRL, OSC_INPUT,  ON); | ||||
|     } | ||||
| 
 | ||||
|     /* Program new power mode. */ | ||||
|     POKE32(POWER_MODE_CTRL, control_value); | ||||
| } | ||||
| 
 | ||||
| void setCurrentGate(unsigned int gate) | ||||
| { | ||||
|     unsigned int gate_reg; | ||||
|     unsigned int mode; | ||||
| 
 | ||||
|     /* Get current power mode. */ | ||||
|     mode = getPowerMode(); | ||||
| 
 | ||||
|     switch (mode) | ||||
|     { | ||||
|         case POWER_MODE_CTRL_MODE_MODE0: | ||||
|             gate_reg = MODE0_GATE; | ||||
|             break; | ||||
| 
 | ||||
|         case POWER_MODE_CTRL_MODE_MODE1: | ||||
|             gate_reg = MODE1_GATE; | ||||
|             break; | ||||
| 
 | ||||
|         default: | ||||
|             gate_reg = MODE0_GATE; | ||||
|             break; | ||||
|     } | ||||
|     POKE32(gate_reg, gate); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the 2D engine. | ||||
|  */ | ||||
| void enable2DEngine(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|     { | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, DE,  ON); | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, DE,  OFF); | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF); | ||||
|     } | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the ZV Port. | ||||
|  */ | ||||
| void enableZVPort(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     /* Enable ZV Port Gate */ | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|     { | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, ON); | ||||
| #if 1 | ||||
|         /* Using Software I2C */ | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON); | ||||
| #else | ||||
|         /* Using Hardware I2C */ | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, I2C,    ON); | ||||
| #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         /* Disable ZV Port Gate. There is no way to know whether the GPIO pins are being used
 | ||||
|            or not. Therefore, do not disable the GPIO gate. */ | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF); | ||||
|     } | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void enableSSP(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     /* Enable SSP Gate */ | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, SSP, ON); | ||||
|     else | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, SSP, OFF); | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| void enableDMA(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     /* Enable DMA Gate */ | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON); | ||||
|     else | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF); | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the GPIO Engine | ||||
|  */ | ||||
| void enableGPIO(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     /* Enable GPIO Gate */ | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON); | ||||
|     else | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF); | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the PWM Engine | ||||
|  */ | ||||
| void enablePWM(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     /* Enable PWM Gate */ | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, PWM, ON); | ||||
|     else | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, PWM, OFF); | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the I2C Engine | ||||
|  */ | ||||
| void enableI2C(unsigned int enable) | ||||
| { | ||||
|     uint32_t gate; | ||||
| 
 | ||||
|     /* Enable I2C Gate */ | ||||
|     gate = PEEK32(CURRENT_GATE); | ||||
|     if (enable) | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON); | ||||
|     else | ||||
|         gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF); | ||||
| 
 | ||||
|     setCurrentGate(gate); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										71
									
								
								drivers/staging/sm750fb/ddk750_power.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								drivers/staging/sm750fb/ddk750_power.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| #ifndef DDK750_POWER_H__ | ||||
| #define DDK750_POWER_H__ | ||||
| 
 | ||||
| typedef enum _DPMS_t | ||||
| { | ||||
|     crtDPMS_ON = 0x0, | ||||
|     crtDPMS_STANDBY = 0x1, | ||||
|     crtDPMS_SUSPEND = 0x2, | ||||
|     crtDPMS_OFF = 0x3, | ||||
| } | ||||
| DPMS_t; | ||||
| 
 | ||||
| #define setDAC(off) \ | ||||
| 		{	\ | ||||
| 		POKE32(MISC_CTRL,FIELD_VALUE(PEEK32(MISC_CTRL),	\ | ||||
| 									MISC_CTRL,	\ | ||||
| 									DAC_POWER,	\ | ||||
| 									off));	\ | ||||
| 		} | ||||
| 
 | ||||
| void ddk750_setDPMS(DPMS_t); | ||||
| 
 | ||||
| unsigned int getPowerMode(void); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function sets the current power mode | ||||
|  */ | ||||
| void setPowerMode(unsigned int powerMode); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function sets current gate | ||||
|  */ | ||||
| void setCurrentGate(unsigned int gate); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the 2D engine. | ||||
|  */ | ||||
| void enable2DEngine(unsigned int enable); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the ZV Port | ||||
|  */ | ||||
| void enableZVPort(unsigned int enable); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the DMA Engine | ||||
|  */ | ||||
| void enableDMA(unsigned int enable); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the GPIO Engine | ||||
|  */ | ||||
| void enableGPIO(unsigned int enable); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the PWM Engine | ||||
|  */ | ||||
| void enablePWM(unsigned int enable); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the I2C Engine | ||||
|  */ | ||||
| void enableI2C(unsigned int enable); | ||||
| 
 | ||||
| /*
 | ||||
|  * This function enable/disable the SSP. | ||||
|  */ | ||||
| void enableSSP(unsigned int enable); | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										2616
									
								
								drivers/staging/sm750fb/ddk750_reg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2616
									
								
								drivers/staging/sm750fb/ddk750_reg.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										425
									
								
								drivers/staging/sm750fb/ddk750_sii164.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										425
									
								
								drivers/staging/sm750fb/ddk750_sii164.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,425 @@ | ||||
| #define USE_DVICHIP | ||||
| #ifdef USE_DVICHIP | ||||
| 
 | ||||
| #include "ddk750_sii164.h" | ||||
| #include "ddk750_hwi2c.h" | ||||
| 
 | ||||
| /* I2C Address of each SII164 chip */ | ||||
| #define SII164_I2C_ADDRESS                  0x70 | ||||
| 
 | ||||
| /* Define this definition to use hardware i2c. */ | ||||
| #define USE_HW_I2C | ||||
| 
 | ||||
| #ifdef USE_HW_I2C | ||||
|     #define i2cWriteReg hwI2CWriteReg | ||||
|     #define i2cReadReg  hwI2CReadReg | ||||
| #else | ||||
|     #define i2cWriteReg swI2CWriteReg | ||||
|     #define i2cReadReg  swI2CReadReg | ||||
| #endif | ||||
| 
 | ||||
| /* SII164 Vendor and Device ID */ | ||||
| #define SII164_VENDOR_ID                    0x0001 | ||||
| #define SII164_DEVICE_ID                    0x0006 | ||||
| 
 | ||||
| #ifdef SII164_FULL_FUNCTIONS | ||||
| /* Name of the DVI Controller chip */ | ||||
| static char *gDviCtrlChipName = "Silicon Image SiI 164"; | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164GetVendorID | ||||
|  *      This function gets the vendor ID of the DVI controller chip. | ||||
|  * | ||||
|  *  Output: | ||||
|  *      Vendor ID | ||||
|  */ | ||||
| unsigned short sii164GetVendorID() | ||||
| { | ||||
|     unsigned short vendorID; | ||||
| 
 | ||||
|     vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) | | ||||
|                 (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW); | ||||
| 
 | ||||
|     return vendorID; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164GetDeviceID | ||||
|  *      This function gets the device ID of the DVI controller chip. | ||||
|  * | ||||
|  *  Output: | ||||
|  *      Device ID | ||||
|  */ | ||||
| unsigned short sii164GetDeviceID() | ||||
| { | ||||
|     unsigned short deviceID; | ||||
| 
 | ||||
|     deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) | | ||||
|                 (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW); | ||||
| 
 | ||||
|     return deviceID; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* DVI.C will handle all SiI164 chip stuffs and try it best to make code minimal and useful */ | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164InitChip | ||||
|  *      This function initialize and detect the DVI controller chip. | ||||
|  * | ||||
|  *  Input: | ||||
|  *      edgeSelect          - Edge Select: | ||||
|  *                              0 = Input data is falling edge latched (falling edge | ||||
|  *                                  latched first in dual edge mode) | ||||
|  *                              1 = Input data is rising edge latched (rising edge | ||||
|  *                                  latched first in dual edge mode) | ||||
|  *      busSelect           - Input Bus Select: | ||||
|  *                              0 = Input data bus is 12-bits wide | ||||
|  *                              1 = Input data bus is 24-bits wide | ||||
|  *      dualEdgeClkSelect   - Dual Edge Clock Select | ||||
|  *                              0 = Input data is single edge latched | ||||
|  *                              1 = Input data is dual edge latched | ||||
|  *      hsyncEnable         - Horizontal Sync Enable: | ||||
|  *                              0 = HSYNC input is transmitted as fixed LOW | ||||
|  *                              1 = HSYNC input is transmitted as is | ||||
|  *      vsyncEnable         - Vertical Sync Enable: | ||||
|  *                              0 = VSYNC input is transmitted as fixed LOW | ||||
|  *                              1 = VSYNC input is transmitted as is | ||||
|  *      deskewEnable        - De-skewing Enable: | ||||
|  *                              0 = De-skew disabled | ||||
|  *                              1 = De-skew enabled | ||||
|  *      deskewSetting       - De-skewing Setting (increment of 260psec) | ||||
|  *                              0 = 1 step --> minimum setup / maximum hold | ||||
|  *                              1 = 2 step | ||||
|  *                              2 = 3 step | ||||
|  *                              3 = 4 step | ||||
|  *                              4 = 5 step | ||||
|  *                              5 = 6 step | ||||
|  *                              6 = 7 step | ||||
|  *                              7 = 8 step --> maximum setup / minimum hold | ||||
|  *      continuousSyncEnable- SYNC Continuous: | ||||
|  *                              0 = Disable | ||||
|  *                              1 = Enable | ||||
|  *      pllFilterEnable     - PLL Filter Enable | ||||
|  *                              0 = Disable PLL Filter | ||||
|  *                              1 = Enable PLL Filter | ||||
|  *      pllFilterValue      - PLL Filter characteristics: | ||||
|  *                              0~7 (recommended value is 4) | ||||
|  * | ||||
|  *  Output: | ||||
|  *      0   - Success | ||||
|  *     -1   - Fail. | ||||
|  */ | ||||
| long sii164InitChip( | ||||
|     unsigned char edgeSelect, | ||||
|     unsigned char busSelect, | ||||
|     unsigned char dualEdgeClkSelect, | ||||
|     unsigned char hsyncEnable, | ||||
|     unsigned char vsyncEnable, | ||||
|     unsigned char deskewEnable, | ||||
|     unsigned char deskewSetting, | ||||
|     unsigned char continuousSyncEnable, | ||||
|     unsigned char pllFilterEnable, | ||||
|     unsigned char pllFilterValue | ||||
| ) | ||||
| { | ||||
|     //unsigned char ucRegIndex, ucRegValue;
 | ||||
|     //unsigned char ucDeviceAddress,
 | ||||
| 	unsigned char config; | ||||
|     //unsigned long delayCount;
 | ||||
| 
 | ||||
|     /* Initialize the i2c bus */ | ||||
| #ifdef USE_HW_I2C | ||||
|     /* Use fast mode. */ | ||||
|     hwI2CInit(1); | ||||
| #else | ||||
|     swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA); | ||||
| #endif | ||||
| 
 | ||||
|     /* Check if SII164 Chip exists */ | ||||
|     if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) | ||||
|     { | ||||
| 
 | ||||
| #ifdef DDKDEBUG | ||||
|         //sii164PrintRegisterValues();
 | ||||
| #endif | ||||
|         /*
 | ||||
|          *  Initialize SII164 controller chip. | ||||
|          */ | ||||
| 
 | ||||
|         /* Select the edge */ | ||||
|         if (edgeSelect == 0) | ||||
|             config = SII164_CONFIGURATION_LATCH_FALLING; | ||||
|         else | ||||
|             config = SII164_CONFIGURATION_LATCH_RISING; | ||||
| 
 | ||||
|         /* Select bus wide */ | ||||
|         if (busSelect == 0) | ||||
|             config |= SII164_CONFIGURATION_BUS_12BITS; | ||||
|         else | ||||
|             config |= SII164_CONFIGURATION_BUS_24BITS; | ||||
| 
 | ||||
|         /* Select Dual/Single Edge Clock */ | ||||
|         if (dualEdgeClkSelect == 0) | ||||
|             config |= SII164_CONFIGURATION_CLOCK_SINGLE; | ||||
|         else | ||||
|             config |= SII164_CONFIGURATION_CLOCK_DUAL; | ||||
| 
 | ||||
|         /* Select HSync Enable */ | ||||
|         if (hsyncEnable == 0) | ||||
|             config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW; | ||||
|         else | ||||
|             config |= SII164_CONFIGURATION_HSYNC_AS_IS; | ||||
| 
 | ||||
|         /* Select VSync Enable */ | ||||
|         if (vsyncEnable == 0) | ||||
|             config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW; | ||||
|         else | ||||
|             config |= SII164_CONFIGURATION_VSYNC_AS_IS; | ||||
| 
 | ||||
|         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); | ||||
| 
 | ||||
|         /* De-skew enabled with default 111b value.
 | ||||
|            This will fix some artifacts problem in some mode on board 2.2. | ||||
|            Somehow this fix does not affect board 2.1. | ||||
|          */ | ||||
|         if (deskewEnable == 0) | ||||
|             config = SII164_DESKEW_DISABLE; | ||||
|         else | ||||
|             config = SII164_DESKEW_ENABLE; | ||||
| 
 | ||||
|         switch (deskewSetting) | ||||
|         { | ||||
|             case 0: | ||||
|                 config |= SII164_DESKEW_1_STEP; | ||||
|                 break; | ||||
|             case 1: | ||||
|                 config |= SII164_DESKEW_2_STEP; | ||||
|                 break; | ||||
|             case 2: | ||||
|                 config |= SII164_DESKEW_3_STEP; | ||||
|                 break; | ||||
|             case 3: | ||||
|                 config |= SII164_DESKEW_4_STEP; | ||||
|                 break; | ||||
|             case 4: | ||||
|                 config |= SII164_DESKEW_5_STEP; | ||||
|                 break; | ||||
|             case 5: | ||||
|                 config |= SII164_DESKEW_6_STEP; | ||||
|                 break; | ||||
|             case 6: | ||||
|                 config |= SII164_DESKEW_7_STEP; | ||||
|                 break; | ||||
|             case 7: | ||||
|                 config |= SII164_DESKEW_8_STEP; | ||||
|                 break; | ||||
|         } | ||||
|         i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config); | ||||
| 
 | ||||
|         /* Enable/Disable Continuous Sync. */ | ||||
|         if (continuousSyncEnable == 0) | ||||
|             config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE; | ||||
|         else | ||||
|             config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE; | ||||
| 
 | ||||
|         /* Enable/Disable PLL Filter */ | ||||
|         if (pllFilterEnable == 0) | ||||
|             config |= SII164_PLL_FILTER_DISABLE; | ||||
|         else | ||||
|             config |= SII164_PLL_FILTER_ENABLE; | ||||
| 
 | ||||
|         /* Set the PLL Filter value */ | ||||
|         config |= ((pllFilterValue & 0x07) << 1); | ||||
| 
 | ||||
|         i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config); | ||||
| 
 | ||||
|         /* Recover from Power Down and enable output. */ | ||||
|         config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION); | ||||
|         config |= SII164_CONFIGURATION_POWER_NORMAL; | ||||
|         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); | ||||
| 
 | ||||
| #ifdef DDKDEBUG | ||||
|         //sii164PrintRegisterValues();
 | ||||
| #endif | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     /* Return -1 if initialization fails. */ | ||||
|     return (-1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* below sii164 function is not neccessary */ | ||||
| 
 | ||||
| #ifdef SII164_FULL_FUNCTIONS | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164ResetChip | ||||
|  *      This function resets the DVI Controller Chip. | ||||
|  */ | ||||
| void sii164ResetChip() | ||||
| { | ||||
|     /* Power down */ | ||||
|     sii164SetPower(0); | ||||
|     sii164SetPower(1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * sii164GetChipString | ||||
|  *      This function returns a char string name of the current DVI Controller chip. | ||||
|  *      It's convenient for application need to display the chip name. | ||||
|  */ | ||||
| char *sii164GetChipString() | ||||
| { | ||||
|     return gDviCtrlChipName; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164SetPower | ||||
|  *      This function sets the power configuration of the DVI Controller Chip. | ||||
|  * | ||||
|  *  Input: | ||||
|  *      powerUp - Flag to set the power down or up | ||||
|  */ | ||||
| void sii164SetPower( | ||||
|     unsigned char powerUp | ||||
| ) | ||||
| { | ||||
|     unsigned char config; | ||||
| 
 | ||||
|     config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION); | ||||
|     if (powerUp == 1) | ||||
|     { | ||||
|         /* Power up the chip */ | ||||
|         config &= ~SII164_CONFIGURATION_POWER_MASK; | ||||
|         config |= SII164_CONFIGURATION_POWER_NORMAL; | ||||
|         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         /* Power down the chip */ | ||||
|         config &= ~SII164_CONFIGURATION_POWER_MASK; | ||||
|         config |= SII164_CONFIGURATION_POWER_DOWN; | ||||
|         i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164SelectHotPlugDetectionMode | ||||
|  *      This function selects the mode of the hot plug detection. | ||||
|  */ | ||||
| static void sii164SelectHotPlugDetectionMode( | ||||
|     sii164_hot_plug_mode_t hotPlugMode | ||||
| ) | ||||
| { | ||||
|     unsigned char detectReg; | ||||
| 
 | ||||
|     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG; | ||||
|     switch (hotPlugMode) | ||||
|     { | ||||
|         case SII164_HOTPLUG_DISABLE: | ||||
|             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH; | ||||
|             break; | ||||
|         case SII164_HOTPLUG_USE_MDI: | ||||
|             detectReg &= ~SII164_DETECT_INTERRUPT_MASK; | ||||
|             detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN; | ||||
|             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI; | ||||
|             break; | ||||
|         case SII164_HOTPLUG_USE_RSEN: | ||||
|             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN; | ||||
|             break; | ||||
|         case SII164_HOTPLUG_USE_HTPLG: | ||||
|             detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG; | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164EnableHotPlugDetection | ||||
|  *      This function enables the Hot Plug detection. | ||||
|  * | ||||
|  *  enableHotPlug   - Enable (=1) / disable (=0) Hot Plug detection | ||||
|  */ | ||||
| void sii164EnableHotPlugDetection( | ||||
|     unsigned char enableHotPlug | ||||
| ) | ||||
| { | ||||
|     unsigned char detectReg; | ||||
|     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); | ||||
| 
 | ||||
|     /* Depending on each DVI controller, need to enable the hot plug based on each
 | ||||
|        individual chip design. */ | ||||
|     if (enableHotPlug != 0) | ||||
|         sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI); | ||||
|     else | ||||
|         sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164IsConnected | ||||
|  *      Check if the DVI Monitor is connected. | ||||
|  * | ||||
|  *  Output: | ||||
|  *      0   - Not Connected | ||||
|  *      1   - Connected | ||||
|  */ | ||||
| unsigned char sii164IsConnected() | ||||
| { | ||||
|     unsigned char hotPlugValue; | ||||
| 
 | ||||
|     hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK; | ||||
|     if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON) | ||||
|         return 1; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164CheckInterrupt | ||||
|  *      Checks if interrupt has occured. | ||||
|  * | ||||
|  *  Output: | ||||
|  *      0   - No interrupt | ||||
|  *      1   - Interrupt occurs | ||||
|  */ | ||||
| unsigned char sii164CheckInterrupt() | ||||
| { | ||||
|     unsigned char detectReg; | ||||
| 
 | ||||
|     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK; | ||||
|     if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE) | ||||
|         return 1; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  sii164ClearInterrupt | ||||
|  *      Clear the hot plug interrupt. | ||||
|  */ | ||||
| void sii164ClearInterrupt() | ||||
| { | ||||
|     unsigned char detectReg; | ||||
| 
 | ||||
|     /* Clear the MDI interrupt */ | ||||
|     detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT); | ||||
|     i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										172
									
								
								drivers/staging/sm750fb/ddk750_sii164.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								drivers/staging/sm750fb/ddk750_sii164.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,172 @@ | ||||
| #ifndef DDK750_SII164_H__ | ||||
| #define DDK750_SII164_H__ | ||||
| 
 | ||||
| #define USE_DVICHIP | ||||
| 
 | ||||
| /* Hot Plug detection mode structure */ | ||||
| typedef enum _sii164_hot_plug_mode_t | ||||
| { | ||||
|     SII164_HOTPLUG_DISABLE = 0,         /* Disable Hot Plug output bit (always high). */ | ||||
|     SII164_HOTPLUG_USE_MDI,             /* Use Monitor Detect Interrupt bit. */ | ||||
|     SII164_HOTPLUG_USE_RSEN,            /* Use Receiver Sense detect bit. */ | ||||
|     SII164_HOTPLUG_USE_HTPLG            /* Use Hot Plug detect bit. */ | ||||
| } sii164_hot_plug_mode_t; | ||||
| 
 | ||||
| 
 | ||||
| /* Silicon Image SiI164 chip prototype */ | ||||
| long sii164InitChip( | ||||
|     unsigned char edgeSelect, | ||||
|     unsigned char busSelect, | ||||
|     unsigned char dualEdgeClkSelect, | ||||
|     unsigned char hsyncEnable, | ||||
|     unsigned char vsyncEnable, | ||||
|     unsigned char deskewEnable, | ||||
|     unsigned char deskewSetting, | ||||
|     unsigned char continuousSyncEnable, | ||||
|     unsigned char pllFilterEnable, | ||||
|     unsigned char pllFilterValue | ||||
| ); | ||||
| 
 | ||||
| unsigned short sii164GetVendorID(void); | ||||
| unsigned short sii164GetDeviceID(void); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef SII164_FULL_FUNCTIONS | ||||
| void sii164ResetChip(void); | ||||
| char *sii164GetChipString(void); | ||||
| void sii164SetPower(unsigned char powerUp); | ||||
| void sii164EnableHotPlugDetection(unsigned char enableHotPlug); | ||||
| unsigned char sii164IsConnected(void); | ||||
| unsigned char sii164CheckInterrupt(void); | ||||
| void sii164ClearInterrupt(void); | ||||
| #endif | ||||
| /* below register definination is used for Silicon Image SiI164 DVI controller chip */ | ||||
| /*
 | ||||
|  * Vendor ID registers | ||||
|  */ | ||||
| #define SII164_VENDOR_ID_LOW                        0x00 | ||||
| #define SII164_VENDOR_ID_HIGH                       0x01 | ||||
| 
 | ||||
| /*
 | ||||
|  * Device ID registers | ||||
|  */ | ||||
| #define SII164_DEVICE_ID_LOW                        0x02 | ||||
| #define SII164_DEVICE_ID_HIGH                       0x03 | ||||
| 
 | ||||
| /*
 | ||||
|  * Device Revision | ||||
|  */ | ||||
| #define SII164_DEVICE_REVISION                      0x04 | ||||
| 
 | ||||
| /*
 | ||||
|  * Frequency Limitation registers | ||||
|  */ | ||||
| #define SII164_FREQUENCY_LIMIT_LOW                  0x06 | ||||
| #define SII164_FREQUENCY_LIMIT_HIGH                 0x07 | ||||
| 
 | ||||
| /*
 | ||||
|  * Power Down and Input Signal Configuration registers | ||||
|  */ | ||||
| #define SII164_CONFIGURATION                        0x08 | ||||
| 
 | ||||
| /* Power down (PD) */ | ||||
| #define SII164_CONFIGURATION_POWER_DOWN             0x00 | ||||
| #define SII164_CONFIGURATION_POWER_NORMAL           0x01 | ||||
| #define SII164_CONFIGURATION_POWER_MASK             0x01 | ||||
| 
 | ||||
| /* Input Edge Latch Select (EDGE) */ | ||||
| #define SII164_CONFIGURATION_LATCH_FALLING          0x00 | ||||
| #define SII164_CONFIGURATION_LATCH_RISING           0x02 | ||||
| 
 | ||||
| /* Bus Select (BSEL) */ | ||||
| #define SII164_CONFIGURATION_BUS_12BITS             0x00 | ||||
| #define SII164_CONFIGURATION_BUS_24BITS             0x04 | ||||
| 
 | ||||
| /* Dual Edge Clock Select (DSEL) */ | ||||
| #define SII164_CONFIGURATION_CLOCK_SINGLE           0x00 | ||||
| #define SII164_CONFIGURATION_CLOCK_DUAL             0x08 | ||||
| 
 | ||||
| /* Horizontal Sync Enable (HEN) */ | ||||
| #define SII164_CONFIGURATION_HSYNC_FORCE_LOW        0x00 | ||||
| #define SII164_CONFIGURATION_HSYNC_AS_IS            0x10 | ||||
| 
 | ||||
| /* Vertical Sync Enable (VEN) */ | ||||
| #define SII164_CONFIGURATION_VSYNC_FORCE_LOW        0x00 | ||||
| #define SII164_CONFIGURATION_VSYNC_AS_IS            0x20 | ||||
| 
 | ||||
| /*
 | ||||
|  * Detection registers | ||||
|  */ | ||||
| #define SII164_DETECT                               0x09 | ||||
| 
 | ||||
| /* Monitor Detect Interrupt (MDI) */ | ||||
| #define SII164_DETECT_MONITOR_STATE_CHANGE          0x00 | ||||
| #define SII164_DETECT_MONITOR_STATE_NO_CHANGE       0x01 | ||||
| #define SII164_DETECT_MONITOR_STATE_CLEAR           0x01 | ||||
| #define SII164_DETECT_MONITOR_STATE_MASK            0x01 | ||||
| 
 | ||||
| /* Hot Plug detect Input (HTPLG) */ | ||||
| #define SII164_DETECT_HOT_PLUG_STATUS_OFF           0x00 | ||||
| #define SII164_DETECT_HOT_PLUG_STATUS_ON            0x02 | ||||
| #define SII164_DETECT_HOT_PLUG_STATUS_MASK          0x02 | ||||
| 
 | ||||
| /* Receiver Sense (RSEN) */ | ||||
| #define SII164_DETECT_RECEIVER_SENSE_NOT_DETECTED   0x00 | ||||
| #define SII164_DETECT_RECEIVER_SENSE_DETECTED       0x04 | ||||
| 
 | ||||
| /* Interrupt Generation Method (TSEL) */ | ||||
| #define SII164_DETECT_INTERRUPT_BY_RSEN_PIN         0x00 | ||||
| #define SII164_DETECT_INTERRUPT_BY_HTPLG_PIN        0x08 | ||||
| #define SII164_DETECT_INTERRUPT_MASK                0x08 | ||||
| 
 | ||||
| /* Monitor Sense Output (MSEN) */ | ||||
| #define SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH     0x00 | ||||
| #define SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI      0x10 | ||||
| #define SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN     0x20 | ||||
| #define SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG    0x30 | ||||
| #define SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG     0x30 | ||||
| 
 | ||||
| /*
 | ||||
|  * Skewing registers | ||||
|  */ | ||||
| #define SII164_DESKEW                               0x0A | ||||
| 
 | ||||
| /* General Purpose Input (CTL[3:1]) */ | ||||
| #define SII164_DESKEW_GENERAL_PURPOSE_INPUT_MASK    0x0E | ||||
| 
 | ||||
| /* De-skewing Enable bit (DKEN) */ | ||||
| #define SII164_DESKEW_DISABLE                       0x00 | ||||
| #define SII164_DESKEW_ENABLE                        0x10 | ||||
| 
 | ||||
| /* De-skewing Setting (DK[3:1])*/ | ||||
| #define SII164_DESKEW_1_STEP                        0x00 | ||||
| #define SII164_DESKEW_2_STEP                        0x20 | ||||
| #define SII164_DESKEW_3_STEP                        0x40 | ||||
| #define SII164_DESKEW_4_STEP                        0x60 | ||||
| #define SII164_DESKEW_5_STEP                        0x80 | ||||
| #define SII164_DESKEW_6_STEP                        0xA0 | ||||
| #define SII164_DESKEW_7_STEP                        0xC0 | ||||
| #define SII164_DESKEW_8_STEP                        0xE0 | ||||
| 
 | ||||
| /*
 | ||||
|  * User Configuration Data registers (CFG 7:0) | ||||
|  */ | ||||
| #define SII164_USER_CONFIGURATION                   0x0B | ||||
| 
 | ||||
| /*
 | ||||
|  * PLL registers | ||||
|  */ | ||||
| #define SII164_PLL                                  0x0C | ||||
| 
 | ||||
| /* PLL Filter Value (PLLF) */ | ||||
| #define SII164_PLL_FILTER_VALUE_MASK                0x0E | ||||
| 
 | ||||
| /* PLL Filter Enable (PFEN) */ | ||||
| #define SII164_PLL_FILTER_DISABLE                   0x00 | ||||
| #define SII164_PLL_FILTER_ENABLE                    0x01 | ||||
| 
 | ||||
| /* Sync Continuous (SCNT) */ | ||||
| #define SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE   0x00 | ||||
| #define SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE    0x80 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										535
									
								
								drivers/staging/sm750fb/ddk750_swi2c.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										535
									
								
								drivers/staging/sm750fb/ddk750_swi2c.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,535 @@ | ||||
| /*******************************************************************
 | ||||
| * | ||||
| *         Copyright (c) 2007 by Silicon Motion, Inc. (SMI) | ||||
| * | ||||
| *  All rights are reserved. Reproduction or in part is prohibited | ||||
| *  without the written consent of the copyright owner. | ||||
| * | ||||
| *  swi2c.c --- SM750/SM718 DDK | ||||
| *  This file contains the source code for I2C using software | ||||
| *  implementation. | ||||
| * | ||||
| *******************************************************************/ | ||||
| #include "ddk750_help.h" | ||||
| #include "ddk750_reg.h" | ||||
| #include "ddk750_swi2c.h" | ||||
| #include "ddk750_power.h" | ||||
| 
 | ||||
| 
 | ||||
| /*******************************************************************
 | ||||
|  * I2C Software Master Driver: | ||||
|  * =========================== | ||||
|  * Each i2c cycle is split into 4 sections. Each of these section marks | ||||
|  * a point in time where the SCL or SDA may be changed. | ||||
|  * | ||||
|  * 1 Cycle == |  Section I. |  Section 2. |  Section 3. |  Section 4. | | ||||
|  *            +-------------+-------------+-------------+-------------+ | ||||
|  *            | SCL set LOW |SCL no change| SCL set HIGH|SCL no change| | ||||
|  * | ||||
|  *                                          ____________ _____________ | ||||
|  * SCL == XXXX _____________ ____________ / | ||||
|  * | ||||
|  * I.e. the SCL may only be changed in section 1. and section 3. while | ||||
|  * the SDA may only be changed in section 2. and section 4. The table | ||||
|  * below gives the changes for these 2 lines in the varios sections. | ||||
|  * | ||||
|  * Section changes Table: | ||||
|  * ====================== | ||||
|  * blank = no change, L = set bit LOW, H = set bit HIGH | ||||
|  * | ||||
|  *                                | 1.| 2.| 3.| 4.| | ||||
|  *                 ---------------+---+---+---+---+ | ||||
|  *                 Tx Start   SDA |   | H |   | L | | ||||
|  *                            SCL | L |   | H |   | | ||||
|  *                 ---------------+---+---+---+---+ | ||||
|  *                 Tx Stop    SDA |   | L |   | H | | ||||
|  *                            SCL | L |   | H |   | | ||||
|  *                 ---------------+---+---+---+---+ | ||||
|  *                 Tx bit H   SDA |   | H |   |   | | ||||
|  *                            SCL | L |   | H |   | | ||||
|  *                 ---------------+---+---+---+---+ | ||||
|  *                 Tx bit L   SDA |   | L |   |   | | ||||
|  *                            SCL | L |   | H |   | | ||||
|  *                 ---------------+---+---+---+---+ | ||||
|  * | ||||
|  ******************************************************************/ | ||||
| 
 | ||||
| /* GPIO pins used for this I2C. It ranges from 0 to 63. */ | ||||
| static unsigned char g_i2cClockGPIO = DEFAULT_I2C_SCL; | ||||
| static unsigned char g_i2cDataGPIO = DEFAULT_I2C_SDA; | ||||
| 
 | ||||
| /*
 | ||||
|  *  Below is the variable declaration for the GPIO pin register usage | ||||
|  *  for the i2c Clock and i2c Data. | ||||
|  * | ||||
|  *  Note: | ||||
|  *      Notice that the GPIO usage for the i2c clock and i2c Data are | ||||
|  *      separated. This is to make this code flexible enough when | ||||
|  *      two separate GPIO pins for the clock and data are located | ||||
|  *      in two different GPIO register set (worst case). | ||||
|  */ | ||||
| 
 | ||||
| /* i2c Clock GPIO Register usage */ | ||||
| static unsigned long g_i2cClkGPIOMuxReg = GPIO_MUX; | ||||
| static unsigned long g_i2cClkGPIODataReg = GPIO_DATA; | ||||
| static unsigned long g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; | ||||
| 
 | ||||
| /* i2c Data GPIO Register usage */ | ||||
| static unsigned long g_i2cDataGPIOMuxReg = GPIO_MUX; | ||||
| static unsigned long g_i2cDataGPIODataReg = GPIO_DATA; | ||||
| static unsigned long g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; | ||||
| 
 | ||||
| static unsigned char peekIO(unsigned short port,unsigned short index) | ||||
| { | ||||
| #if defined(__i386__) || defined( __x86_64__) | ||||
| 		outb_p(index,port); | ||||
| 		return inb_p(port+1); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function puts a delay between command | ||||
|  */ | ||||
| static void swI2CWait(void) | ||||
| { | ||||
| 	/* find a bug:
 | ||||
| 	 * peekIO method works well before suspend/resume | ||||
| 	 * but after suspend, peekIO(0x3ce,0x61) & 0x10 | ||||
| 	 * always be non-zero,which makes the while loop | ||||
| 	 * never finish. | ||||
| 	 * use non-ultimate for loop below is safe | ||||
| 	 * */ | ||||
| #if 0 | ||||
|     /* Change wait algorithm to use PCI bus clock,
 | ||||
|        it's more reliable than counter loop .. | ||||
|        write 0x61 to 0x3ce and read from 0x3cf | ||||
|        */ | ||||
| 	while(peekIO(0x3ce,0x61) & 0x10); | ||||
| #else | ||||
|     int i, Temp; | ||||
| 
 | ||||
|     for(i=0; i<600; i++) | ||||
|     { | ||||
|         Temp = i; | ||||
|         Temp += i; | ||||
|     } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function set/reset the SCL GPIO pin | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high) | ||||
|  * | ||||
|  *  Notes: | ||||
|  *      When setting SCL to high, just set the GPIO as input where the pull up | ||||
|  *      resistor will pull the signal up. Do not use software to pull up the | ||||
|  *      signal because the i2c will fail when other device try to drive the | ||||
|  *      signal due to SM50x will drive the signal to always high. | ||||
|  */ | ||||
| void swI2CSCL(unsigned char value) | ||||
| { | ||||
|     unsigned long ulGPIOData; | ||||
|     unsigned long ulGPIODirection; | ||||
| 
 | ||||
|     ulGPIODirection = PEEK32(g_i2cClkGPIODataDirReg); | ||||
|     if (value)      /* High */ | ||||
|     { | ||||
|         /* Set direction as input. This will automatically pull the signal up. */ | ||||
|         ulGPIODirection &= ~(1 << g_i2cClockGPIO); | ||||
|         POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection); | ||||
|     } | ||||
|     else            /* Low */ | ||||
|     { | ||||
|         /* Set the signal down */ | ||||
|         ulGPIOData = PEEK32(g_i2cClkGPIODataReg); | ||||
|         ulGPIOData &= ~(1 << g_i2cClockGPIO); | ||||
|         POKE32(g_i2cClkGPIODataReg, ulGPIOData); | ||||
| 
 | ||||
|         /* Set direction as output */ | ||||
|         ulGPIODirection |= (1 << g_i2cClockGPIO); | ||||
|         POKE32(g_i2cClkGPIODataDirReg, ulGPIODirection); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function set/reset the SDA GPIO pin | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      value    - Bit value to set to the SCL or SDA (0 = low, 1 = high) | ||||
|  * | ||||
|  *  Notes: | ||||
|  *      When setting SCL to high, just set the GPIO as input where the pull up | ||||
|  *      resistor will pull the signal up. Do not use software to pull up the | ||||
|  *      signal because the i2c will fail when other device try to drive the | ||||
|  *      signal due to SM50x will drive the signal to always high. | ||||
|  */ | ||||
| void swI2CSDA(unsigned char value) | ||||
| { | ||||
|     unsigned long ulGPIOData; | ||||
|     unsigned long ulGPIODirection; | ||||
| 
 | ||||
|     ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg); | ||||
|     if (value)      /* High */ | ||||
|     { | ||||
|         /* Set direction as input. This will automatically pull the signal up. */ | ||||
|         ulGPIODirection &= ~(1 << g_i2cDataGPIO); | ||||
|         POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); | ||||
|     } | ||||
|     else            /* Low */ | ||||
|     { | ||||
|         /* Set the signal down */ | ||||
|         ulGPIOData = PEEK32(g_i2cDataGPIODataReg); | ||||
|         ulGPIOData &= ~(1 << g_i2cDataGPIO); | ||||
|         POKE32(g_i2cDataGPIODataReg, ulGPIOData); | ||||
| 
 | ||||
|         /* Set direction as output */ | ||||
|         ulGPIODirection |= (1 << g_i2cDataGPIO); | ||||
|         POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function read the data from the SDA GPIO pin | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      The SDA data bit sent by the Slave | ||||
|  */ | ||||
| static unsigned char swI2CReadSDA(void) | ||||
| { | ||||
|     unsigned long ulGPIODirection; | ||||
|     unsigned long ulGPIOData; | ||||
| 
 | ||||
|     /* Make sure that the direction is input (High) */ | ||||
|     ulGPIODirection = PEEK32(g_i2cDataGPIODataDirReg); | ||||
|     if ((ulGPIODirection & (1 << g_i2cDataGPIO)) != (~(1 << g_i2cDataGPIO))) | ||||
|     { | ||||
|         ulGPIODirection &= ~(1 << g_i2cDataGPIO); | ||||
|         POKE32(g_i2cDataGPIODataDirReg, ulGPIODirection); | ||||
|     } | ||||
| 
 | ||||
|     /* Now read the SDA line */ | ||||
|     ulGPIOData = PEEK32(g_i2cDataGPIODataReg); | ||||
|     if (ulGPIOData & (1 << g_i2cDataGPIO)) | ||||
|         return 1; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
| 
 | ||||
| #pragma optimize( "", off ) | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function sends ACK signal | ||||
|  */ | ||||
| static void swI2CAck(void) | ||||
| { | ||||
|     return;  /* Single byte read is ok without it. */ | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function sends the start command to the slave device | ||||
|  */ | ||||
| void swI2CStart(void) | ||||
| { | ||||
|     /* Start I2C */ | ||||
|     swI2CSDA(1); | ||||
|     swI2CSCL(1); | ||||
|     swI2CSDA(0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function sends the stop command to the slave device | ||||
|  */ | ||||
| void swI2CStop(void) | ||||
| { | ||||
|     /* Stop the I2C */ | ||||
|     swI2CSCL(1); | ||||
|     swI2CSDA(0); | ||||
|     swI2CSDA(1); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function writes one byte to the slave device | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      data    - Data to be write to the slave device | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *       0   - Success | ||||
|  *      -1   - Fail to write byte | ||||
|  */ | ||||
| long swI2CWriteByte(unsigned char data) | ||||
| { | ||||
|     unsigned char value = data; | ||||
|     int i; | ||||
| 
 | ||||
|     /* Sending the data bit by bit */ | ||||
|     for (i=0; i<8; i++) | ||||
|     { | ||||
|         /* Set SCL to low */ | ||||
|         swI2CSCL(0); | ||||
| 
 | ||||
|         /* Send data bit */ | ||||
|         if ((value & 0x80) != 0) | ||||
|             swI2CSDA(1); | ||||
|         else | ||||
|             swI2CSDA(0); | ||||
| 
 | ||||
|         swI2CWait(); | ||||
| 
 | ||||
|         /* Toggle clk line to one */ | ||||
|         swI2CSCL(1); | ||||
|         swI2CWait(); | ||||
| 
 | ||||
|         /* Shift byte to be sent */ | ||||
|         value = value << 1; | ||||
|     } | ||||
| 
 | ||||
|     /* Set the SCL Low and SDA High (prepare to get input) */ | ||||
|     swI2CSCL(0); | ||||
|     swI2CSDA(1); | ||||
| 
 | ||||
|     /* Set the SCL High for ack */ | ||||
|     swI2CWait(); | ||||
|     swI2CSCL(1); | ||||
|     swI2CWait(); | ||||
| 
 | ||||
|     /* Read SDA, until SDA==0 */ | ||||
|     for(i=0; i<0xff; i++) | ||||
|     { | ||||
|         if (!swI2CReadSDA()) | ||||
|             break; | ||||
| 
 | ||||
|         swI2CSCL(0); | ||||
|         swI2CWait(); | ||||
|         swI2CSCL(1); | ||||
|         swI2CWait(); | ||||
|     } | ||||
| 
 | ||||
|     /* Set the SCL Low and SDA High */ | ||||
|     swI2CSCL(0); | ||||
|     swI2CSDA(1); | ||||
| 
 | ||||
|     if (i<0xff) | ||||
|         return 0; | ||||
|     else | ||||
|         return (-1); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function reads one byte from the slave device | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      ack    - Flag to indicate either to send the acknowledge | ||||
|  *            message to the slave device or not | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      One byte data read from the Slave device | ||||
|  */ | ||||
| unsigned char swI2CReadByte(unsigned char ack) | ||||
| { | ||||
|     int i; | ||||
|     unsigned char data = 0; | ||||
| 
 | ||||
|     for(i=7; i>=0; i--) | ||||
|     { | ||||
|         /* Set the SCL to Low and SDA to High (Input) */ | ||||
|         swI2CSCL(0); | ||||
|         swI2CSDA(1); | ||||
|         swI2CWait(); | ||||
| 
 | ||||
|         /* Set the SCL High */ | ||||
|         swI2CSCL(1); | ||||
|         swI2CWait(); | ||||
| 
 | ||||
|         /* Read data bits from SDA */ | ||||
|         data |= (swI2CReadSDA() << i); | ||||
|     } | ||||
| 
 | ||||
|     if (ack) | ||||
|         swI2CAck(); | ||||
| 
 | ||||
|     /* Set the SCL Low and SDA High */ | ||||
|     swI2CSCL(0); | ||||
|     swI2CSDA(1); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
| #pragma optimize( "", on ) | ||||
| 
 | ||||
| /*
 | ||||
|  * This function initializes GPIO port for SW I2C communication. | ||||
|  * | ||||
|  * Parameters: | ||||
|  *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL | ||||
|  *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA | ||||
|  * | ||||
|  * Return Value: | ||||
|  *      -1   - Fail to initialize the i2c | ||||
|  *       0   - Success | ||||
|  */ | ||||
| long swI2CInit_SM750LE( | ||||
|     unsigned char i2cClkGPIO, | ||||
|     unsigned char i2cDataGPIO | ||||
| ) | ||||
| { | ||||
|     int i; | ||||
| 
 | ||||
|     /* Initialize the GPIO pin for the i2c Clock Register */ | ||||
|     g_i2cClkGPIODataReg = GPIO_DATA_SM750LE; | ||||
|     g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; | ||||
| 
 | ||||
|     /* Initialize the Clock GPIO Offset */ | ||||
|     g_i2cClockGPIO = i2cClkGPIO; | ||||
| 
 | ||||
|     /* Initialize the GPIO pin for the i2c Data Register */ | ||||
|     g_i2cDataGPIODataReg = GPIO_DATA_SM750LE; | ||||
|     g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION_SM750LE; | ||||
| 
 | ||||
|     /* Initialize the Data GPIO Offset */ | ||||
|     g_i2cDataGPIO = i2cDataGPIO; | ||||
| 
 | ||||
|     /* Note that SM750LE don't have GPIO MUX and power is always on */ | ||||
| 
 | ||||
|     /* Clear the i2c lines. */ | ||||
|     for(i=0; i<9; i++) | ||||
|         swI2CStop(); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function initializes the i2c attributes and bus | ||||
|  * | ||||
|  * Parameters: | ||||
|  *      i2cClkGPIO      - The GPIO pin to be used as i2c SCL | ||||
|  *      i2cDataGPIO     - The GPIO pin to be used as i2c SDA | ||||
|  * | ||||
|  * Return Value: | ||||
|  *      -1   - Fail to initialize the i2c | ||||
|  *       0   - Success | ||||
|  */ | ||||
| long swI2CInit( | ||||
|     unsigned char i2cClkGPIO, | ||||
|     unsigned char i2cDataGPIO | ||||
| ) | ||||
| { | ||||
|     int i; | ||||
| 
 | ||||
|     /* Return 0 if the GPIO pins to be used is out of range. The range is only from [0..63] */ | ||||
|     if ((i2cClkGPIO > 31) || (i2cDataGPIO > 31)) | ||||
|         return (-1); | ||||
| 
 | ||||
|     if (getChipType() == SM750LE) | ||||
|         return( swI2CInit_SM750LE(i2cClkGPIO, i2cDataGPIO) ); | ||||
| 
 | ||||
|     /* Initialize the GPIO pin for the i2c Clock Register */ | ||||
|     g_i2cClkGPIOMuxReg = GPIO_MUX; | ||||
|     g_i2cClkGPIODataReg = GPIO_DATA; | ||||
|     g_i2cClkGPIODataDirReg = GPIO_DATA_DIRECTION; | ||||
| 
 | ||||
|     /* Initialize the Clock GPIO Offset */ | ||||
|     g_i2cClockGPIO = i2cClkGPIO; | ||||
| 
 | ||||
|     /* Initialize the GPIO pin for the i2c Data Register */ | ||||
|     g_i2cDataGPIOMuxReg = GPIO_MUX; | ||||
|     g_i2cDataGPIODataReg = GPIO_DATA; | ||||
|     g_i2cDataGPIODataDirReg = GPIO_DATA_DIRECTION; | ||||
| 
 | ||||
|     /* Initialize the Data GPIO Offset */ | ||||
|     g_i2cDataGPIO = i2cDataGPIO; | ||||
| 
 | ||||
|     /* Enable the GPIO pins for the i2c Clock and Data (GPIO MUX) */ | ||||
|     POKE32(g_i2cClkGPIOMuxReg, | ||||
|                       PEEK32(g_i2cClkGPIOMuxReg) & ~(1 << g_i2cClockGPIO)); | ||||
|     POKE32(g_i2cDataGPIOMuxReg, | ||||
|                       PEEK32(g_i2cDataGPIOMuxReg) & ~(1 << g_i2cDataGPIO)); | ||||
| 
 | ||||
|     /* Enable GPIO power */ | ||||
|     enableGPIO(1); | ||||
| 
 | ||||
|     /* Clear the i2c lines. */ | ||||
|     for(i=0; i<9; i++) | ||||
|         swI2CStop(); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function reads the slave device's register | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address which register | ||||
|  *                        to be read from | ||||
|  *      registerIndex   - Slave device's register to be read | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      Register value | ||||
|  */ | ||||
| unsigned char swI2CReadReg( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned char registerIndex | ||||
| ) | ||||
| { | ||||
|     unsigned char data; | ||||
| 
 | ||||
|     /* Send the Start signal */ | ||||
|     swI2CStart(); | ||||
| 
 | ||||
|     /* Send the device address */ | ||||
|     swI2CWriteByte(deviceAddress); | ||||
| 
 | ||||
|     /* Send the register index */ | ||||
|     swI2CWriteByte(registerIndex); | ||||
| 
 | ||||
|     /* Get the bus again and get the data from the device read address */ | ||||
|     swI2CStart(); | ||||
|     swI2CWriteByte(deviceAddress + 1); | ||||
|     data = swI2CReadByte(1); | ||||
| 
 | ||||
|     /* Stop swI2C and release the bus */ | ||||
|     swI2CStop(); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function writes a value to the slave device's register | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address which register | ||||
|  *                        to be written | ||||
|  *      registerIndex   - Slave device's register to be written | ||||
|  *      data            - Data to be written to the register | ||||
|  * | ||||
|  *  Result: | ||||
|  *          0   - Success | ||||
|  *         -1   - Fail | ||||
|  */ | ||||
| long swI2CWriteReg( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned char registerIndex, | ||||
|     unsigned char data | ||||
| ) | ||||
| { | ||||
|     long returnValue = 0; | ||||
| 
 | ||||
|     /* Send the Start signal */ | ||||
|     swI2CStart(); | ||||
| 
 | ||||
|     /* Send the device address and read the data. All should return success
 | ||||
|        in order for the writing processed to be successful | ||||
|      */ | ||||
|     if ((swI2CWriteByte(deviceAddress) != 0) || | ||||
|         (swI2CWriteByte(registerIndex) != 0) || | ||||
|         (swI2CWriteByte(data) != 0)) | ||||
|     { | ||||
|         returnValue = -1; | ||||
|     } | ||||
| 
 | ||||
|     /* Stop i2c and release the bus */ | ||||
|     swI2CStop(); | ||||
| 
 | ||||
|     return returnValue; | ||||
| } | ||||
							
								
								
									
										92
									
								
								drivers/staging/sm750fb/ddk750_swi2c.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								drivers/staging/sm750fb/ddk750_swi2c.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| /*******************************************************************
 | ||||
| * | ||||
| *         Copyright (c) 2007 by Silicon Motion, Inc. (SMI) | ||||
| * | ||||
| *  All rights are reserved. Reproduction or in part is prohibited | ||||
| *  without the written consent of the copyright owner. | ||||
| * | ||||
| *  swi2c.h --- SM750/SM718 DDK | ||||
| *  This file contains the definitions for i2c using software | ||||
| *  implementation. | ||||
| * | ||||
| *******************************************************************/ | ||||
| #ifndef _SWI2C_H_ | ||||
| #define _SWI2C_H_ | ||||
| 
 | ||||
| /* Default i2c CLK and Data GPIO. These are the default i2c pins */ | ||||
| #define DEFAULT_I2C_SCL                     30 | ||||
| #define DEFAULT_I2C_SDA                     31 | ||||
| 
 | ||||
| /*
 | ||||
|  * This function initializes the i2c attributes and bus | ||||
|  * | ||||
|  * Parameters: | ||||
|  *      i2cClkGPIO  - The GPIO pin to be used as i2c SCL | ||||
|  *      i2cDataGPIO - The GPIO pin to be used as i2c SDA | ||||
|  * | ||||
|  * Return Value: | ||||
|  *      -1   - Fail to initialize the i2c | ||||
|  *       0   - Success | ||||
|  */ | ||||
| long swI2CInit( | ||||
|     unsigned char i2cClkGPIO, | ||||
|     unsigned char i2cDataGPIO | ||||
| ); | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function reads the slave device's register | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address which register | ||||
|  *                        to be read from | ||||
|  *      registerIndex   - Slave device's register to be read | ||||
|  * | ||||
|  *  Return Value: | ||||
|  *      Register value | ||||
|  */ | ||||
| unsigned char swI2CReadReg( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned char registerIndex | ||||
| ); | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function writes a value to the slave device's register | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      deviceAddress   - i2c Slave device address which register | ||||
|  *                        to be written | ||||
|  *      registerIndex   - Slave device's register to be written | ||||
|  *      data            - Data to be written to the register | ||||
|  * | ||||
|  *  Result: | ||||
|  *          0   - Success | ||||
|  *         -1   - Fail | ||||
|  */ | ||||
| long swI2CWriteReg( | ||||
|     unsigned char deviceAddress, | ||||
|     unsigned char registerIndex, | ||||
|     unsigned char data | ||||
| ); | ||||
| 
 | ||||
| /*
 | ||||
|  *  These two functions are used to toggle the data on the SCL and SDA I2C lines. | ||||
|  *  The used of these two functions are not recommended unless it is necessary. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function set/reset the SCL GPIO pin | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      value	- Bit value to set to the SCL or SDA (0 = low, 1 = high) | ||||
|  */ | ||||
| void swI2CSCL(unsigned char value); | ||||
| 
 | ||||
| /*
 | ||||
|  *  This function set/reset the SDA GPIO pin | ||||
|  * | ||||
|  *  Parameters: | ||||
|  *      value	- Bit value to set to the SCL or SDA (0 = low, 1 = high) | ||||
|  */ | ||||
| void swI2CSDA(unsigned char value); | ||||
| 
 | ||||
| #endif  /* _SWI2C_H_ */ | ||||
							
								
								
									
										221
									
								
								drivers/staging/sm750fb/modedb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								drivers/staging/sm750fb/modedb.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,221 @@ | ||||
| 
 | ||||
| static const struct fb_videomode modedb2[] = { | ||||
|     { | ||||
| 	/* 640x400 @ 70 Hz, 31.5 kHz hsync */ | ||||
| 	NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 640x480 @ 60 Hz, 31.5 kHz hsync */ | ||||
| 	NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 800x600 @ 56 Hz, 35.15 kHz hsync */ | ||||
| 	NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ | ||||
| 	NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, | ||||
| 	0, FB_VMODE_INTERLACED | ||||
|     }, { | ||||
| 	/* 640x400 @ 85 Hz, 37.86 kHz hsync */ | ||||
| 	NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, | ||||
| 	FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 640x480 @ 72 Hz, 36.5 kHz hsync */ | ||||
| 	NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 640x480 @ 75 Hz, 37.50 kHz hsync */ | ||||
| 	NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 800x600 @ 60 Hz, 37.8 kHz hsync */ | ||||
| 	NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 640x480 @ 85 Hz, 43.27 kHz hsync */ | ||||
| 	NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ | ||||
| 	NULL, 69, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, | ||||
| 	0, FB_VMODE_INTERLACED | ||||
|     }, { | ||||
| 	/* 800x600 @ 72 Hz, 48.0 kHz hsync */ | ||||
| 	NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1024x768 @ 60 Hz, 48.4 kHz hsync */ | ||||
| 	NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 640x480 @ 100 Hz, 53.01 kHz hsync */ | ||||
| 	NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1152x864 @ 60 Hz, 53.5 kHz hsync */ | ||||
| 	NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 800x600 @ 85 Hz, 55.84 kHz hsync */ | ||||
| 	NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1024x768 @ 70 Hz, 56.5 kHz hsync */ | ||||
| 	NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
|         /*  1280x960-60 VESA */ | ||||
|         NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, | ||||
|         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA | ||||
|     }, { | ||||
|         /*  1280x1024-60 VESA */ | ||||
|         NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||||
|         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ | ||||
| 	NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, | ||||
| 	0, FB_VMODE_INTERLACED | ||||
|     }, { | ||||
| 	/* 800x600 @ 100 Hz, 64.02 kHz hsync */ | ||||
| 	NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1024x768 @ 76 Hz, 62.5 kHz hsync */ | ||||
| 	NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1152x864 @ 70 Hz, 62.4 kHz hsync */ | ||||
| 	NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ | ||||
| 	NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1400x1050 @ 60Hz, 63.9 kHz hsync */ | ||||
| 	NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/ | ||||
| 	NULL, 75, 1400, 1050, 9271, 120, 56, 13, 0, 112, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/ | ||||
|         NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1024x768 @ 85 Hz, 70.24 kHz hsync */ | ||||
| 	NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1152x864 @ 78 Hz, 70.8 kHz hsync */ | ||||
| 	NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ | ||||
| 	NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1600x1200 @ 60Hz, 75.00 kHz hsync */ | ||||
| 	NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1152x864 @ 84 Hz, 76.0 kHz hsync */ | ||||
| 	NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ | ||||
| 	NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1024x768 @ 100Hz, 80.21 kHz hsync */ | ||||
| 	NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ | ||||
| 	NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ | ||||
| 	NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1152x864 @ 100 Hz, 89.62 kHz hsync */ | ||||
| 	NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ | ||||
| 	NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ | ||||
| 	NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ | ||||
| 	NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ | ||||
| 	NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1800x1440 @ 64Hz, 96.15 kHz hsync  */ | ||||
| 	NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 1800x1440 @ 70Hz, 104.52 kHz hsync  */ | ||||
| 	NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, | ||||
| 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 512x384 @ 78 Hz, 31.50 kHz hsync */ | ||||
| 	NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 512x384 @ 85 Hz, 34.38 kHz hsync */ | ||||
| 	NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, | ||||
| 	0, FB_VMODE_NONINTERLACED | ||||
|     }, { | ||||
| 	/* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ | ||||
| 	NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ | ||||
| 	NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 320x240 @ 72 Hz, 36.5 kHz hsync */ | ||||
| 	NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ | ||||
| 	NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 400x300 @ 60 Hz, 37.8 kHz hsync */ | ||||
| 	NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 400x300 @ 72 Hz, 48.0 kHz hsync */ | ||||
| 	NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ | ||||
| 	NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 480x300 @ 60 Hz, 37.8 kHz hsync */ | ||||
| 	NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 480x300 @ 63 Hz, 39.6 kHz hsync */ | ||||
| 	NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, { | ||||
| 	/* 480x300 @ 72 Hz, 48.0 kHz hsync */ | ||||
| 	NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, | ||||
| 	0, FB_VMODE_DOUBLE | ||||
|     }, | ||||
| }; | ||||
| static const int nmodedb2 = sizeof(modedb2); | ||||
							
								
								
									
										38
									
								
								drivers/staging/sm750fb/readme
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								drivers/staging/sm750fb/readme
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| Introduction: | ||||
| 	SM750 of Silicon MOtion is pci express display controller device. | ||||
| 	The SM750 embedded graphics features include: | ||||
| 	- dual display | ||||
| 	- 2D acceleration | ||||
| 	- 16MB integrated video memory | ||||
| 
 | ||||
| About the kernel module paramter of driver: | ||||
| 
 | ||||
| 	Use 1280,8bpp index color and 60 hz mode: | ||||
| 	insmod ./sm750fb.ko g_option="1280x1024-8@60" | ||||
| 
 | ||||
| 	Disable MTRR,Disable 2d acceleration,Disable hardware cursor, | ||||
| 	and use a 800x600 mode : | ||||
| 	insmod ./sm750fb.ko g_option="noaccel:nomtrr:nohwc:800x600" | ||||
| 
 | ||||
| 	dual frame buffer for driver with "dual" parameter | ||||
| 	insmod ./sm750fb.ko g_option="dual,800x600:1024x768" | ||||
| 	it will create fb0 and fb1 (or fb1,fb2 if fb0 already exist) under /dev | ||||
| 	and user can use con2fb to link fbX and ttyX | ||||
| 
 | ||||
| 	Notes: | ||||
| 	1) if you build the driver with built-in method, the paramter | ||||
| 		you edited in the grub config file will be also the | ||||
| 		same format as above modular method,but additionaly add | ||||
| 		"video=sm750fb:" | ||||
| 		ahead of parameters,so,it looks like: | ||||
| 		video=sm750fb:noaccel,1280x1024@60,otherparam,etc... | ||||
| 		it equal to modular method with below command: | ||||
| 		insmod ./sm750fb.ko g_option="noaccel:1280x1024@60:otherparm:etc..." | ||||
| 
 | ||||
| 	2) if you put 800x600 into the paramter without bpp and | ||||
| 		refresh rate, kernel driver will defaulty use 16bpp and 60hz | ||||
| 
 | ||||
| Important: | ||||
| 	if you have vesafb enabled in your config then /dev/fb0 will be created by vesafb | ||||
| 	and this driver will use fb1, fb2. In that case, you need to configure your X-server | ||||
| 	to use fb1. Another simple althernative is to disable vesafb from your config. | ||||
							
								
								
									
										1451
									
								
								drivers/staging/sm750fb/sm750.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1451
									
								
								drivers/staging/sm750fb/sm750.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										185
									
								
								drivers/staging/sm750fb/sm750.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								drivers/staging/sm750fb/sm750.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,185 @@ | ||||
| #ifndef LYNXDRV_H_ | ||||
| #define LYNXDRV_H_ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #define FB_ACCEL_SMI 0xab | ||||
| /* please use revision id to distinguish sm750le and sm750*/ | ||||
| #define SPC_SM750 	0 | ||||
| 
 | ||||
| //#define SPC_SM750LE 8
 | ||||
| 
 | ||||
| #define MB(x) ((x)<<20) | ||||
| #define MHZ(x) ((x) * 1000000) | ||||
| /* align should be 2,4,8,16 */ | ||||
| #define PADDING(align,data) (((data)+(align)-1)&(~((align) -1))) | ||||
| extern int smi_indent; | ||||
| 
 | ||||
| 
 | ||||
| struct lynx_accel{ | ||||
| 	/* base virtual address of DPR registers */ | ||||
| 	volatile unsigned char __iomem * dprBase; | ||||
| 	/* base virtual address of de data port */ | ||||
| 	volatile unsigned char __iomem * dpPortBase; | ||||
| 
 | ||||
| 	/* function fointers */ | ||||
| 	int (*de_init)(struct lynx_accel *); | ||||
| 
 | ||||
| 	int (*de_wait)(void);/* see if hardware ready to work */ | ||||
| 
 | ||||
| 	int (*de_fillrect)(struct lynx_accel *,u32,u32,u32, | ||||
| 							u32,u32,u32,u32,u32,u32); | ||||
| 
 | ||||
| 	int (*de_copyarea)(struct lynx_accel *,u32,u32,u32,u32, | ||||
| 						u32,u32,u32,u32, | ||||
| 						u32,u32,u32,u32); | ||||
| 
 | ||||
| 	int (*de_imageblit)(struct lynx_accel *,const char *,u32,u32,u32, | ||||
| 						u32,u32,u32,u32,u32,u32,u32,u32,u32); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| /* 	lynx_share stands for a presentation of two frame buffer
 | ||||
| 	that use one smi adaptor , it is similar to a basic class of C++ | ||||
| */ | ||||
| struct lynx_share{ | ||||
| 	/* common members */ | ||||
| 	u16 devid; | ||||
| 	u8 revid; | ||||
| 	struct pci_dev * pdev; | ||||
| 	struct fb_info * fbinfo[2]; | ||||
| 	struct lynx_accel accel; | ||||
| 	int accel_off; | ||||
| 	int dual; | ||||
| #ifdef CONFIG_MTRR | ||||
| 		int mtrr_off; | ||||
| 		struct{ | ||||
| 			int vram; | ||||
| 			int vram_added; | ||||
| 		}mtrr; | ||||
| #endif | ||||
| 	/* all smi graphic adaptor got below attributes */ | ||||
| 	resource_size_t vidmem_start; | ||||
| 	resource_size_t vidreg_start; | ||||
| 	resource_size_t vidmem_size; | ||||
| 	resource_size_t vidreg_size; | ||||
| 	volatile unsigned char __iomem * pvReg; | ||||
| 	unsigned char __iomem * pvMem; | ||||
| 	/* locks*/ | ||||
| 	spinlock_t slock; | ||||
| 	/* function pointers */ | ||||
| 	void (*suspend)(struct lynx_share*); | ||||
| 	void (*resume)(struct lynx_share*); | ||||
| }; | ||||
| 
 | ||||
| struct lynx_cursor{ | ||||
| 	/* cursor width ,height and size */ | ||||
| 	int w; | ||||
| 	int h; | ||||
| 	int size; | ||||
| 	/* hardware limitation */ | ||||
| 	int maxW; | ||||
| 	int maxH; | ||||
| 	/* base virtual address and offset  of cursor image */ | ||||
| 	char __iomem * vstart; | ||||
| 	int offset; | ||||
| 	/* mmio addr of hw cursor */ | ||||
| 	volatile char __iomem * mmio; | ||||
| 	/* the lynx_share of this adaptor */ | ||||
| 	struct lynx_share * share; | ||||
| 	/* proc_routines */ | ||||
| 	void (*enable)(struct lynx_cursor *); | ||||
| 	void (*disable)(struct lynx_cursor *); | ||||
| 	void (*setSize)(struct lynx_cursor *,int,int); | ||||
| 	void (*setPos)(struct lynx_cursor *,int,int); | ||||
| 	void (*setColor)(struct lynx_cursor *,u32,u32); | ||||
| 	void (*setData)(struct lynx_cursor *,u16,const u8*,const u8*); | ||||
| }; | ||||
| 
 | ||||
| struct lynxfb_crtc{ | ||||
| 	unsigned char __iomem * vCursor;//virtual address of cursor
 | ||||
| 	unsigned char __iomem * vScreen;//virtual address of on_screen
 | ||||
| 	int oCursor;//cursor address offset in vidmem
 | ||||
| 	int oScreen;//onscreen address offset in vidmem
 | ||||
| 	int channel;/* which channel this crtc stands for*/ | ||||
| 	resource_size_t vidmem_size;/* this view's video memory max size */ | ||||
| 
 | ||||
| 	/* below attributes belong to info->fix, their value depends on specific adaptor*/ | ||||
| 	u16 line_pad;/* padding information:0,1,2,4,8,16,... */ | ||||
| 	u16 xpanstep; | ||||
| 	u16 ypanstep; | ||||
| 	u16 ywrapstep; | ||||
| 
 | ||||
| 	void * priv; | ||||
| 
 | ||||
| 	int(*proc_setMode)(struct lynxfb_crtc*, | ||||
| 						struct fb_var_screeninfo*, | ||||
| 						struct fb_fix_screeninfo*); | ||||
| 
 | ||||
| 	int(*proc_checkMode)(struct lynxfb_crtc*,struct fb_var_screeninfo*); | ||||
| 	int(*proc_setColReg)(struct lynxfb_crtc*,ushort,ushort,ushort,ushort); | ||||
| 	void (*clear)(struct lynxfb_crtc*); | ||||
|         /* pan display */ | ||||
|         int(*proc_panDisplay)(struct lynxfb_crtc*, struct fb_var_screeninfo*, | ||||
|                 struct fb_info*); | ||||
| 	/* cursor information */ | ||||
| 	struct lynx_cursor cursor; | ||||
| }; | ||||
| 
 | ||||
| struct lynxfb_output{ | ||||
| 	int dpms; | ||||
| 	int paths; | ||||
| 	/* 	which paths(s) this output stands for,for sm750:
 | ||||
| 		paths=1:means output for panel paths | ||||
| 		paths=2:means output for crt paths | ||||
| 		paths=3:means output for both panel and crt paths | ||||
| 	*/ | ||||
| 
 | ||||
| 	int * channel; | ||||
| 	/* 	which channel these outputs linked with,for sm750:
 | ||||
| 		*channel=0 means primary channel | ||||
| 		*channel=1 means secondary channel | ||||
| 		output->channel ==> &crtc->channel | ||||
| 	*/ | ||||
| 	void * priv; | ||||
| 
 | ||||
| 	int(*proc_setMode)(struct lynxfb_output*, | ||||
| 						struct fb_var_screeninfo*, | ||||
| 						struct fb_fix_screeninfo*); | ||||
| 
 | ||||
| 	int(*proc_checkMode)(struct lynxfb_output*,struct fb_var_screeninfo*); | ||||
| 	int(*proc_setBLANK)(struct lynxfb_output*,int); | ||||
| 	void  (*clear)(struct lynxfb_output*); | ||||
| }; | ||||
| 
 | ||||
| struct lynxfb_par{ | ||||
| 	/* either 0 or 1 for dual head adaptor,0 is the older one registered */ | ||||
| 	int index; | ||||
| 	unsigned int pseudo_palette[256]; | ||||
| 	struct lynxfb_crtc crtc; | ||||
| 	struct lynxfb_output output; | ||||
| 	struct fb_info * info; | ||||
| 	struct lynx_share * share; | ||||
| }; | ||||
| 
 | ||||
| #ifndef offsetof | ||||
| #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #define PS_TO_HZ(ps)	\ | ||||
| 			({ 	\ | ||||
| 			unsigned long long hz = 1000*1000*1000*1000ULL;	\ | ||||
| 			do_div(hz,ps);	\ | ||||
| 			(unsigned long)hz;}) | ||||
| 
 | ||||
| static inline unsigned long ps_to_hz(unsigned int psvalue) | ||||
| { | ||||
| 	unsigned long long numerator=1000*1000*1000*1000ULL; | ||||
| 	/* 10^12 / picosecond period gives frequency in Hz */ | ||||
| 	do_div(numerator, psvalue); | ||||
| 	return (unsigned long)numerator; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										516
									
								
								drivers/staging/sm750fb/sm750_accel.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										516
									
								
								drivers/staging/sm750fb/sm750_accel.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,516 @@ | ||||
| #include<linux/module.h> | ||||
| #include<linux/kernel.h> | ||||
| #include<linux/errno.h> | ||||
| #include<linux/string.h> | ||||
| #include<linux/mm.h> | ||||
| #include<linux/slab.h> | ||||
| #include<linux/delay.h> | ||||
| #include<linux/fb.h> | ||||
| #include<linux/ioport.h> | ||||
| #include<linux/init.h> | ||||
| #include<linux/pci.h> | ||||
| #include<linux/vmalloc.h> | ||||
| #include<linux/pagemap.h> | ||||
| #include <linux/console.h> | ||||
| #include<linux/platform_device.h> | ||||
| #include<linux/screen_info.h> | ||||
| 
 | ||||
| #include "sm750.h" | ||||
| #include "sm750_accel.h" | ||||
| #include "sm750_help.h" | ||||
| static inline void write_dpr(struct lynx_accel * accel,int offset,u32 regValue) | ||||
| { | ||||
| 	writel(regValue,accel->dprBase + offset); | ||||
| } | ||||
| 
 | ||||
| static inline u32 read_dpr(struct lynx_accel * accel,int offset) | ||||
| { | ||||
| 	return readl(accel->dprBase + offset); | ||||
| } | ||||
| 
 | ||||
| static inline void write_dpPort(struct lynx_accel * accel,u32 data) | ||||
| { | ||||
| 	writel(data,accel->dpPortBase); | ||||
| } | ||||
| 
 | ||||
| void hw_de_init(struct lynx_accel * accel) | ||||
| { | ||||
| 	/* setup 2d engine registers */ | ||||
| 	u32 reg,clr; | ||||
| 	 | ||||
| 	write_dpr(accel,DE_MASKS,0xFFFFFFFF); | ||||
| 
 | ||||
| 	/* dpr1c */ | ||||
| 	reg = FIELD_SET(0,DE_STRETCH_FORMAT,PATTERN_XY,NORMAL)| | ||||
| 		FIELD_VALUE(0,DE_STRETCH_FORMAT,PATTERN_Y,0)| | ||||
| 		FIELD_VALUE(0,DE_STRETCH_FORMAT,PATTERN_X,0)| | ||||
| 		FIELD_SET(0,DE_STRETCH_FORMAT,ADDRESSING,XY)| | ||||
| 		FIELD_VALUE(0,DE_STRETCH_FORMAT,SOURCE_HEIGHT,3); | ||||
| 
 | ||||
| 	clr = FIELD_CLEAR(DE_STRETCH_FORMAT,PATTERN_XY)& | ||||
| 		FIELD_CLEAR(DE_STRETCH_FORMAT,PATTERN_Y)& | ||||
| 		FIELD_CLEAR(DE_STRETCH_FORMAT,PATTERN_X)& | ||||
| 		FIELD_CLEAR(DE_STRETCH_FORMAT,ADDRESSING)& | ||||
| 		FIELD_CLEAR(DE_STRETCH_FORMAT,SOURCE_HEIGHT); | ||||
| 
 | ||||
| 	/* DE_STRETCH bpp format need be initilized in setMode routine */ | ||||
| 	write_dpr(accel,DE_STRETCH_FORMAT,(read_dpr(accel,DE_STRETCH_FORMAT) & clr) | reg); | ||||
| 
 | ||||
| 	/* disable clipping and transparent */ | ||||
| 	write_dpr(accel,DE_CLIP_TL,0);//dpr2c
 | ||||
| 	write_dpr(accel,DE_CLIP_BR,0);//dpr30
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_COLOR_COMPARE_MASK,0);//dpr24
 | ||||
| 	write_dpr(accel,DE_COLOR_COMPARE,0); | ||||
| 
 | ||||
| 	reg = FIELD_SET(0,DE_CONTROL,TRANSPARENCY,DISABLE)| | ||||
| 		FIELD_SET(0,DE_CONTROL,TRANSPARENCY_MATCH,OPAQUE)| | ||||
| 		FIELD_SET(0,DE_CONTROL,TRANSPARENCY_SELECT,SOURCE); | ||||
| 
 | ||||
| 	clr = FIELD_CLEAR(DE_CONTROL,TRANSPARENCY)& | ||||
| 		FIELD_CLEAR(DE_CONTROL,TRANSPARENCY_MATCH)& | ||||
| 		FIELD_CLEAR(DE_CONTROL,TRANSPARENCY_SELECT); | ||||
| 
 | ||||
| 	/* dpr0c */ | ||||
| 	write_dpr(accel,DE_CONTROL,(read_dpr(accel,DE_CONTROL)&clr)|reg); | ||||
| } | ||||
| 
 | ||||
| /* set2dformat only be called from setmode functions
 | ||||
|  * but if you need dual framebuffer driver,need call set2dformat | ||||
|  * every time you use 2d function */ | ||||
| 
 | ||||
| void hw_set2dformat(struct lynx_accel * accel,int fmt) | ||||
| { | ||||
| 	u32 reg; | ||||
| 	 | ||||
| 	/* fmt=0,1,2 for 8,16,32,bpp on sm718/750/502 */ | ||||
| 	reg = read_dpr(accel,DE_STRETCH_FORMAT); | ||||
| 	reg = FIELD_VALUE(reg,DE_STRETCH_FORMAT,PIXEL_FORMAT,fmt); | ||||
| 	write_dpr(accel,DE_STRETCH_FORMAT,reg); | ||||
| } | ||||
| 
 | ||||
| /* seems sm712 RectFill command is broken,so need use BitBlt to
 | ||||
|  * replace it. */ | ||||
| 
 | ||||
| int hw712_fillrect(struct lynx_accel * accel, | ||||
| 				u32 base,u32 pitch,u32 Bpp, | ||||
| 				u32 x,u32 y,u32 width,u32 height, | ||||
| 				u32 color,u32 rop) | ||||
| { | ||||
| 	u32 deCtrl; | ||||
| 	if(accel->de_wait() != 0) | ||||
| 	{ | ||||
| 		/* int time wait and always busy,seems hardware
 | ||||
| 		 * got something error */ | ||||
| 		pr_debug("%s:De engine always bussy\n",__func__); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	/* 24bpp 2d acceleration still not work,we already support 2d on
 | ||||
| 	 * both 8/16/32 bpp now, so there is no harm if we disable 2d on | ||||
| 	 * 24bpp for current stage. */ | ||||
| #if 0 | ||||
| 	if(Bpp == 3){ | ||||
| 		width *= 3; | ||||
| 		x *= 3; | ||||
| 		write_dpr(accel,DE_PITCH, | ||||
| 			FIELD_VALUE(0,DE_PITCH,DESTINATION,pitch)| | ||||
| 			FIELD_VALUE(0,DE_PITCH,SOURCE,pitch));//dpr10
 | ||||
| 	} | ||||
| 	else | ||||
| #endif | ||||
| 	{ | ||||
| 		write_dpr(accel,DE_PITCH, | ||||
| 			FIELD_VALUE(0,DE_PITCH,DESTINATION,pitch/Bpp)| | ||||
| 			FIELD_VALUE(0,DE_PITCH,SOURCE,pitch/Bpp));//dpr10
 | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	write_dpr(accel,DE_FOREGROUND,color);//DPR14
 | ||||
| 	write_dpr(accel,DE_MONO_PATTERN_HIGH,~0);//DPR34
 | ||||
| 	write_dpr(accel,DE_MONO_PATTERN_LOW,~0);//DPR38
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_WINDOW_SOURCE_BASE,base);//dpr44
 | ||||
| 	write_dpr(accel,DE_WINDOW_DESTINATION_BASE,base);//dpr40
 | ||||
| 
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_WINDOW_WIDTH, | ||||
| 			FIELD_VALUE(0,DE_WINDOW_WIDTH,DESTINATION,pitch/Bpp)| | ||||
| 			FIELD_VALUE(0,DE_WINDOW_WIDTH,SOURCE,pitch/Bpp));//dpr3c
 | ||||
| 
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_DESTINATION, | ||||
| 			FIELD_SET(0,DE_DESTINATION,WRAP,DISABLE)| | ||||
| 			FIELD_VALUE(0,DE_DESTINATION,X,x)| | ||||
| 			FIELD_VALUE(0,DE_DESTINATION,Y,y));//dpr4
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_DIMENSION, | ||||
| 			FIELD_VALUE(0,DE_DIMENSION,X,width)| | ||||
| 			FIELD_VALUE(0,DE_DIMENSION,Y_ET,height));//dpr8
 | ||||
| 
 | ||||
| 	deCtrl = | ||||
| 		FIELD_SET(0,DE_CONTROL,STATUS,START)| | ||||
| 		FIELD_SET(0,DE_CONTROL,COMMAND,BITBLT)| | ||||
| 		FIELD_SET(0,DE_CONTROL,ROP2_SOURCE,PATTERN)| | ||||
| 		FIELD_SET(0,DE_CONTROL,ROP_SELECT,ROP2)| | ||||
| 		FIELD_VALUE(0,DE_CONTROL,ROP,rop);//dpr0xc
 | ||||
| #if 0 | ||||
| 		/* dump registers */ | ||||
| 		int i; | ||||
| 		inf_msg("x,y,w,h = %d,%d,%d,%d\n",x,y,width,height); | ||||
| 		for(i=0x04;i<=0x44;i+=4){ | ||||
| 			inf_msg("dpr%02x = %08x\n",i,read_dpr(accel,i)); | ||||
| 		} | ||||
| 		inf_msg("deCtrl = %08x\n",deCtrl); | ||||
| #endif | ||||
| 
 | ||||
| 	write_dpr(accel,DE_CONTROL,deCtrl); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int hw_fillrect(struct lynx_accel * accel, | ||||
| 				u32 base,u32 pitch,u32 Bpp, | ||||
| 				u32 x,u32 y,u32 width,u32 height, | ||||
| 				u32 color,u32 rop) | ||||
| { | ||||
| 	u32 deCtrl; | ||||
| 
 | ||||
| 	if(accel->de_wait() != 0) | ||||
| 	{ | ||||
| 		/* int time wait and always busy,seems hardware
 | ||||
| 		 * got something error */ | ||||
| 		pr_debug("%s:De engine always bussy\n",__func__); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	write_dpr(accel,DE_WINDOW_DESTINATION_BASE,base);//dpr40
 | ||||
| 	write_dpr(accel,DE_PITCH, | ||||
| 			FIELD_VALUE(0,DE_PITCH,DESTINATION,pitch/Bpp)| | ||||
| 			FIELD_VALUE(0,DE_PITCH,SOURCE,pitch/Bpp));//dpr10
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_WINDOW_WIDTH, | ||||
| 			FIELD_VALUE(0,DE_WINDOW_WIDTH,DESTINATION,pitch/Bpp)| | ||||
| 			FIELD_VALUE(0,DE_WINDOW_WIDTH,SOURCE,pitch/Bpp));//dpr44
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_FOREGROUND,color);//DPR14
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_DESTINATION, | ||||
| 			FIELD_SET(0,DE_DESTINATION,WRAP,DISABLE)| | ||||
| 			FIELD_VALUE(0,DE_DESTINATION,X,x)| | ||||
| 			FIELD_VALUE(0,DE_DESTINATION,Y,y));//dpr4
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_DIMENSION, | ||||
| 			FIELD_VALUE(0,DE_DIMENSION,X,width)| | ||||
| 			FIELD_VALUE(0,DE_DIMENSION,Y_ET,height));//dpr8
 | ||||
| 
 | ||||
| 	deCtrl = | ||||
| 		FIELD_SET(0,DE_CONTROL,STATUS,START)| | ||||
| 		FIELD_SET(0,DE_CONTROL,DIRECTION,LEFT_TO_RIGHT)| | ||||
| 		FIELD_SET(0,DE_CONTROL,LAST_PIXEL,ON)| | ||||
| 		FIELD_SET(0,DE_CONTROL,COMMAND,RECTANGLE_FILL)| | ||||
| 		FIELD_SET(0,DE_CONTROL,ROP_SELECT,ROP2)| | ||||
| 		FIELD_VALUE(0,DE_CONTROL,ROP,rop);//dpr0xc
 | ||||
| 
 | ||||
| 	write_dpr(accel,DE_CONTROL,deCtrl); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int hw_copyarea( | ||||
| struct lynx_accel * accel, | ||||
| unsigned int sBase,  /* Address of source: offset in frame buffer */ | ||||
| unsigned int sPitch, /* Pitch value of source surface in BYTE */ | ||||
| unsigned int sx, | ||||
| unsigned int sy,     /* Starting coordinate of source surface */ | ||||
| unsigned int dBase,  /* Address of destination: offset in frame buffer */ | ||||
| unsigned int dPitch, /* Pitch value of destination surface in BYTE */ | ||||
| unsigned int Bpp,    /* Color depth of destination surface */ | ||||
| unsigned int dx, | ||||
| unsigned int dy,     /* Starting coordinate of destination surface */ | ||||
| unsigned int width, | ||||
| unsigned int height, /* width and height of rectangle in pixel value */ | ||||
| unsigned int rop2)   /* ROP value */ | ||||
| { | ||||
|     unsigned int nDirection, de_ctrl; | ||||
|     int opSign; | ||||
|     nDirection = LEFT_TO_RIGHT; | ||||
| 	/* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */ | ||||
|     opSign = 1; | ||||
|     de_ctrl = 0; | ||||
| 
 | ||||
|     /* If source and destination are the same surface, need to check for overlay cases */ | ||||
|     if (sBase == dBase && sPitch == dPitch) | ||||
|     { | ||||
|         /* Determine direction of operation */ | ||||
|         if (sy < dy) | ||||
|         { | ||||
|             /* +----------+
 | ||||
|                |S         | | ||||
|                |   +----------+ | ||||
|                |   |      |   | | ||||
|                |   |      |   | | ||||
|                +---|------+   | | ||||
|                    |         D| | ||||
|                    +----------+ */ | ||||
| 
 | ||||
|             nDirection = BOTTOM_TO_TOP; | ||||
|         } | ||||
|         else if (sy > dy) | ||||
|         { | ||||
|             /* +----------+
 | ||||
|                |D         | | ||||
|                |   +----------+ | ||||
|                |   |      |   | | ||||
|                |   |      |   | | ||||
|                +---|------+   | | ||||
|                    |         S| | ||||
|                    +----------+ */ | ||||
| 
 | ||||
|             nDirection = TOP_TO_BOTTOM; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             /* sy == dy */ | ||||
| 
 | ||||
|             if (sx <= dx) | ||||
|             { | ||||
|                 /* +------+---+------+
 | ||||
|                    |S     |   |     D| | ||||
|                    |      |   |      | | ||||
|                    |      |   |      | | ||||
|                    |      |   |      | | ||||
|                    +------+---+------+ */ | ||||
| 
 | ||||
|                 nDirection = RIGHT_TO_LEFT; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 /* sx > dx */ | ||||
| 
 | ||||
|                 /* +------+---+------+
 | ||||
|                    |D     |   |     S| | ||||
|                    |      |   |      | | ||||
|                    |      |   |      | | ||||
|                    |      |   |      | | ||||
|                    +------+---+------+ */ | ||||
| 
 | ||||
|                 nDirection = LEFT_TO_RIGHT; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) | ||||
|     { | ||||
|         sx += width - 1; | ||||
|         sy += height - 1; | ||||
|         dx += width - 1; | ||||
|         dy += height - 1; | ||||
|         opSign = (-1); | ||||
|     } | ||||
| 
 | ||||
|     /* Note:
 | ||||
|        DE_FOREGROUND are DE_BACKGROUND are don't care. | ||||
|        DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency(). | ||||
|     */ | ||||
| 
 | ||||
|     /* 2D Source Base.
 | ||||
|        It is an address offset (128 bit aligned) from the beginning of frame buffer. | ||||
|     */ | ||||
|     write_dpr(accel,DE_WINDOW_SOURCE_BASE, sBase);//dpr40
 | ||||
| 
 | ||||
|     /* 2D Destination Base.
 | ||||
|        It is an address offset (128 bit aligned) from the beginning of frame buffer. | ||||
|     */ | ||||
|     write_dpr(accel,DE_WINDOW_DESTINATION_BASE, dBase);//dpr44
 | ||||
| 
 | ||||
| #if 0 | ||||
|     /* Program pitch (distance between the 1st points of two adjacent lines).
 | ||||
|        Note that input pitch is BYTE value, but the 2D Pitch register uses | ||||
|        pixel values. Need Byte to pixel convertion. | ||||
|     */ | ||||
| 	if(Bpp == 3){ | ||||
| 			sx *= 3; | ||||
| 			dx *= 3; | ||||
| 			width *= 3; | ||||
| 		write_dpr(accel,DE_PITCH, | ||||
| 				FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) | | ||||
| 				FIELD_VALUE(0, DE_PITCH, SOURCE,      sPitch));//dpr10
 | ||||
| 	} | ||||
| 	else | ||||
| #endif | ||||
| 	{ | ||||
| 		write_dpr(accel,DE_PITCH, | ||||
| 				FIELD_VALUE(0, DE_PITCH, DESTINATION, (dPitch/Bpp)) | | ||||
| 				FIELD_VALUE(0, DE_PITCH, SOURCE,      (sPitch/Bpp)));//dpr10
 | ||||
| 	} | ||||
| 
 | ||||
|     /* Screen Window width in Pixels.
 | ||||
|        2D engine uses this value to calculate the linear address in frame buffer for a given point. | ||||
|     */ | ||||
|     write_dpr(accel,DE_WINDOW_WIDTH, | ||||
|         FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) | | ||||
|         FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (sPitch/Bpp)));//dpr3c
 | ||||
| 
 | ||||
| 	if (accel->de_wait() != 0){ | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
|     { | ||||
| 
 | ||||
|         write_dpr(accel,DE_SOURCE, | ||||
|             FIELD_SET  (0, DE_SOURCE, WRAP, DISABLE) | | ||||
|             FIELD_VALUE(0, DE_SOURCE, X_K1, sx)   | | ||||
|             FIELD_VALUE(0, DE_SOURCE, Y_K2, sy));//dpr0
 | ||||
|         write_dpr(accel,DE_DESTINATION, | ||||
|             FIELD_SET  (0, DE_DESTINATION, WRAP, DISABLE) | | ||||
|             FIELD_VALUE(0, DE_DESTINATION, X,    dx)  | | ||||
|             FIELD_VALUE(0, DE_DESTINATION, Y,    dy));//dpr04
 | ||||
|         write_dpr(accel,DE_DIMENSION, | ||||
|             FIELD_VALUE(0, DE_DIMENSION, X,    width) | | ||||
|             FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));//dpr08
 | ||||
| 
 | ||||
|         de_ctrl = | ||||
|             FIELD_VALUE(0, DE_CONTROL, ROP, rop2) | | ||||
|             FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | | ||||
|             FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) | | ||||
|             ((nDirection == RIGHT_TO_LEFT) ? | ||||
|             FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT) | ||||
|             : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) | | ||||
|             FIELD_SET(0, DE_CONTROL, STATUS, START); | ||||
| 		write_dpr(accel,DE_CONTROL,de_ctrl);//dpr0c
 | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static unsigned int deGetTransparency(struct lynx_accel * accel) | ||||
| { | ||||
|     unsigned int de_ctrl; | ||||
| 
 | ||||
|     de_ctrl = read_dpr(accel,DE_CONTROL); | ||||
| 
 | ||||
|     de_ctrl &= | ||||
|         FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) | | ||||
|         FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)| | ||||
|         FIELD_MASK(DE_CONTROL_TRANSPARENCY); | ||||
| 
 | ||||
|     return de_ctrl; | ||||
| } | ||||
| 
 | ||||
| int hw_imageblit( | ||||
| struct lynx_accel * accel, | ||||
| unsigned char *pSrcbuf, /* pointer to start of source buffer in system memory */ | ||||
| int srcDelta,          /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */ | ||||
| unsigned int startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */ | ||||
| unsigned int dBase,    /* Address of destination: offset in frame buffer */ | ||||
| unsigned int dPitch,   /* Pitch value of destination surface in BYTE */ | ||||
| unsigned int bytePerPixel,      /* Color depth of destination surface */ | ||||
| unsigned int dx, | ||||
| unsigned int dy,       /* Starting coordinate of destination surface */ | ||||
| unsigned int width, | ||||
| unsigned int height,   /* width and height of rectange in pixel value */ | ||||
| unsigned int fColor,   /* Foreground color (corresponding to a 1 in the monochrome data */ | ||||
| unsigned int bColor,   /* Background color (corresponding to a 0 in the monochrome data */ | ||||
| unsigned int rop2)     /* ROP value */ | ||||
| { | ||||
|     unsigned int ulBytesPerScan; | ||||
|     unsigned int ul4BytesPerScan; | ||||
|     unsigned int ulBytesRemain; | ||||
|     unsigned int de_ctrl = 0; | ||||
|     unsigned char ajRemain[4]; | ||||
|     int i, j; | ||||
| 
 | ||||
|     startBit &= 7; /* Just make sure the start bit is within legal range */ | ||||
|     ulBytesPerScan = (width + startBit + 7) / 8; | ||||
|     ul4BytesPerScan = ulBytesPerScan & ~3; | ||||
|     ulBytesRemain = ulBytesPerScan & 3; | ||||
| 
 | ||||
| 	if(accel->de_wait() != 0) | ||||
|     { | ||||
| //		inf_msg("*** ImageBlit return -1 ***\n");
 | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     /* 2D Source Base.
 | ||||
|        Use 0 for HOST Blt. | ||||
|     */ | ||||
|     write_dpr(accel,DE_WINDOW_SOURCE_BASE, 0); | ||||
| 
 | ||||
|     /* 2D Destination Base.
 | ||||
|        It is an address offset (128 bit aligned) from the beginning of frame buffer. | ||||
|     */ | ||||
|     write_dpr(accel,DE_WINDOW_DESTINATION_BASE, dBase); | ||||
| #if 0 | ||||
|     /* Program pitch (distance between the 1st points of two adjacent lines).
 | ||||
|        Note that input pitch is BYTE value, but the 2D Pitch register uses | ||||
|        pixel values. Need Byte to pixel convertion. | ||||
|     */ | ||||
| 	if(bytePerPixel == 3 ){ | ||||
| 		dx *= 3; | ||||
| 		width *= 3; | ||||
| 		startBit *= 3; | ||||
| 		write_dpr(accel,DE_PITCH, | ||||
| 				FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) | | ||||
| 				FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch));//dpr10
 | ||||
| 
 | ||||
| 	} | ||||
| 	else | ||||
| #endif | ||||
| 	{ | ||||
| 		write_dpr(accel,DE_PITCH, | ||||
| 				FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch/bytePerPixel) | | ||||
| 				FIELD_VALUE(0, DE_PITCH, SOURCE,      dPitch/bytePerPixel));//dpr10
 | ||||
| 	} | ||||
| 
 | ||||
|     /* Screen Window width in Pixels.
 | ||||
|        2D engine uses this value to calculate the linear address in frame buffer for a given point. | ||||
|     */ | ||||
|     write_dpr(accel,DE_WINDOW_WIDTH, | ||||
|         FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) | | ||||
|         FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE,      (dPitch/bytePerPixel))); | ||||
| 
 | ||||
|     /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
 | ||||
|              For mono bitmap, use startBit for X_K1. */ | ||||
|     write_dpr(accel,DE_SOURCE, | ||||
|         FIELD_SET  (0, DE_SOURCE, WRAP, DISABLE)       | | ||||
|         FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit));//dpr00
 | ||||
| 
 | ||||
|     write_dpr(accel,DE_DESTINATION, | ||||
|         FIELD_SET  (0, DE_DESTINATION, WRAP, DISABLE) | | ||||
|         FIELD_VALUE(0, DE_DESTINATION, X,    dx)    | | ||||
|         FIELD_VALUE(0, DE_DESTINATION, Y,    dy));//dpr04
 | ||||
| 
 | ||||
|     write_dpr(accel,DE_DIMENSION, | ||||
|         FIELD_VALUE(0, DE_DIMENSION, X,    width) | | ||||
|         FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));//dpr08
 | ||||
| 
 | ||||
|     write_dpr(accel,DE_FOREGROUND, fColor); | ||||
|     write_dpr(accel,DE_BACKGROUND, bColor); | ||||
| 
 | ||||
| 	de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2)         | | ||||
| 		FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2)    | | ||||
| 		FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) | | ||||
| 		FIELD_SET(0, DE_CONTROL, HOST, MONO)          | | ||||
| 		FIELD_SET(0, DE_CONTROL, STATUS, START); | ||||
| 
 | ||||
| 	write_dpr(accel,DE_CONTROL, de_ctrl | deGetTransparency(accel)); | ||||
| 
 | ||||
|     /* Write MONO data (line by line) to 2D Engine data port */ | ||||
|     for (i=0; i<height; i++) | ||||
|     { | ||||
|         /* For each line, send the data in chunks of 4 bytes */ | ||||
|         for (j=0; j<(ul4BytesPerScan/4); j++) | ||||
|         { | ||||
|             write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4))); | ||||
|         } | ||||
| 
 | ||||
|         if (ulBytesRemain) | ||||
|         { | ||||
|             memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain); | ||||
|             write_dpPort(accel, *(unsigned int *)ajRemain); | ||||
|         } | ||||
| 
 | ||||
|         pSrcbuf += srcDelta; | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										276
									
								
								drivers/staging/sm750fb/sm750_accel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								drivers/staging/sm750fb/sm750_accel.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,276 @@ | ||||
| #ifndef ACCEL_H__ | ||||
| #define ACCEL_H__ | ||||
| 
 | ||||
| #define HW_ROP2_COPY 0xc | ||||
| #define HW_ROP2_XOR 0x6 | ||||
| 
 | ||||
| /* notes: below address are the offset value from de_base_address (0x100000)*/ | ||||
| 
 | ||||
| /* for sm718/750/502 de_base is at mmreg_1mb*/ | ||||
| #define DE_BASE_ADDR_TYPE1 	0x100000 | ||||
| /* for sm712,de_base is at mmreg_32kb */ | ||||
| #define DE_BASE_ADDR_TYPE2  0x8000 | ||||
| /* for sm722,de_base is at mmreg_0 */ | ||||
| #define DE_BASE_ADDR_TYPE3 0 | ||||
| 
 | ||||
| /* type1 data port address is at mmreg_0x110000*/ | ||||
| #define DE_PORT_ADDR_TYPE1 0x110000 | ||||
| /* for sm712,data port address is at mmreg_0 */ | ||||
| #define DE_PORT_ADDR_TYPE2 0x100000 | ||||
| /* for sm722,data port address is at mmreg_1mb */ | ||||
| #define DE_PORT_ADDR_TYPE3 0x100000 | ||||
| 
 | ||||
| #define DE_SOURCE                                       0x0 | ||||
| #define DE_SOURCE_WRAP                                  31:31 | ||||
| #define DE_SOURCE_WRAP_DISABLE                          0 | ||||
| #define DE_SOURCE_WRAP_ENABLE                           1 | ||||
| #define DE_SOURCE_X_K1                                  29:16 | ||||
| #define DE_SOURCE_Y_K2                                  15:0 | ||||
| #define DE_SOURCE_X_K1_MONO 							20:16 | ||||
| 
 | ||||
| #define DE_DESTINATION                                  0x4 | ||||
| #define DE_DESTINATION_WRAP                             31:31 | ||||
| #define DE_DESTINATION_WRAP_DISABLE                     0 | ||||
| #define DE_DESTINATION_WRAP_ENABLE                      1 | ||||
| #define DE_DESTINATION_X                                28:16 | ||||
| #define DE_DESTINATION_Y                                15:0 | ||||
| 
 | ||||
| #define DE_DIMENSION                                    0x8 | ||||
| #define DE_DIMENSION_X                                  28:16 | ||||
| #define DE_DIMENSION_Y_ET                               15:0 | ||||
| 
 | ||||
| #define DE_CONTROL                                      0xC | ||||
| #define DE_CONTROL_STATUS                               31:31 | ||||
| #define DE_CONTROL_STATUS_STOP                          0 | ||||
| #define DE_CONTROL_STATUS_START                         1 | ||||
| #define DE_CONTROL_PATTERN                              30:30 | ||||
| #define DE_CONTROL_PATTERN_MONO                         0 | ||||
| #define DE_CONTROL_PATTERN_COLOR                        1 | ||||
| #define DE_CONTROL_UPDATE_DESTINATION_X                 29:29 | ||||
| #define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE         0 | ||||
| #define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE          1 | ||||
| #define DE_CONTROL_QUICK_START                          28:28 | ||||
| #define DE_CONTROL_QUICK_START_DISABLE                  0 | ||||
| #define DE_CONTROL_QUICK_START_ENABLE                   1 | ||||
| #define DE_CONTROL_DIRECTION                            27:27 | ||||
| #define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT              0 | ||||
| #define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT              1 | ||||
| #define DE_CONTROL_MAJOR                                26:26 | ||||
| #define DE_CONTROL_MAJOR_X                              0 | ||||
| #define DE_CONTROL_MAJOR_Y                              1 | ||||
| #define DE_CONTROL_STEP_X                               25:25 | ||||
| #define DE_CONTROL_STEP_X_POSITIVE                      1 | ||||
| #define DE_CONTROL_STEP_X_NEGATIVE                      0 | ||||
| #define DE_CONTROL_STEP_Y                               24:24 | ||||
| #define DE_CONTROL_STEP_Y_POSITIVE                      1 | ||||
| #define DE_CONTROL_STEP_Y_NEGATIVE                      0 | ||||
| #define DE_CONTROL_STRETCH                              23:23 | ||||
| #define DE_CONTROL_STRETCH_DISABLE                      0 | ||||
| #define DE_CONTROL_STRETCH_ENABLE                       1 | ||||
| #define DE_CONTROL_HOST                                 22:22 | ||||
| #define DE_CONTROL_HOST_COLOR                           0 | ||||
| #define DE_CONTROL_HOST_MONO                            1 | ||||
| #define DE_CONTROL_LAST_PIXEL                           21:21 | ||||
| #define DE_CONTROL_LAST_PIXEL_OFF                       0 | ||||
| #define DE_CONTROL_LAST_PIXEL_ON                        1 | ||||
| #define DE_CONTROL_COMMAND                              20:16 | ||||
| #define DE_CONTROL_COMMAND_BITBLT                       0 | ||||
| #define DE_CONTROL_COMMAND_RECTANGLE_FILL               1 | ||||
| #define DE_CONTROL_COMMAND_DE_TILE                      2 | ||||
| #define DE_CONTROL_COMMAND_TRAPEZOID_FILL               3 | ||||
| #define DE_CONTROL_COMMAND_ALPHA_BLEND                  4 | ||||
| #define DE_CONTROL_COMMAND_RLE_STRIP                    5 | ||||
| #define DE_CONTROL_COMMAND_SHORT_STROKE                 6 | ||||
| #define DE_CONTROL_COMMAND_LINE_DRAW                    7 | ||||
| #define DE_CONTROL_COMMAND_HOST_WRITE                   8 | ||||
| #define DE_CONTROL_COMMAND_HOST_READ                    9 | ||||
| #define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP         10 | ||||
| #define DE_CONTROL_COMMAND_ROTATE                       11 | ||||
| #define DE_CONTROL_COMMAND_FONT                         12 | ||||
| #define DE_CONTROL_COMMAND_TEXTURE_LOAD                 15 | ||||
| #define DE_CONTROL_ROP_SELECT                           15:15 | ||||
| #define DE_CONTROL_ROP_SELECT_ROP3                      0 | ||||
| #define DE_CONTROL_ROP_SELECT_ROP2                      1 | ||||
| #define DE_CONTROL_ROP2_SOURCE                          14:14 | ||||
| #define DE_CONTROL_ROP2_SOURCE_BITMAP                   0 | ||||
| #define DE_CONTROL_ROP2_SOURCE_PATTERN                  1 | ||||
| #define DE_CONTROL_MONO_DATA                            13:12 | ||||
| #define DE_CONTROL_MONO_DATA_NOT_PACKED                 0 | ||||
| #define DE_CONTROL_MONO_DATA_8_PACKED                   1 | ||||
| #define DE_CONTROL_MONO_DATA_16_PACKED                  2 | ||||
| #define DE_CONTROL_MONO_DATA_32_PACKED                  3 | ||||
| #define DE_CONTROL_REPEAT_ROTATE                        11:11 | ||||
| #define DE_CONTROL_REPEAT_ROTATE_DISABLE                0 | ||||
| #define DE_CONTROL_REPEAT_ROTATE_ENABLE                 1 | ||||
| #define DE_CONTROL_TRANSPARENCY_MATCH                   10:10 | ||||
| #define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE            0 | ||||
| #define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT       1 | ||||
| #define DE_CONTROL_TRANSPARENCY_SELECT                  9:9 | ||||
| #define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE           0 | ||||
| #define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION      1 | ||||
| #define DE_CONTROL_TRANSPARENCY                         8:8 | ||||
| #define DE_CONTROL_TRANSPARENCY_DISABLE                 0 | ||||
| #define DE_CONTROL_TRANSPARENCY_ENABLE                  1 | ||||
| #define DE_CONTROL_ROP                                  7:0 | ||||
| 
 | ||||
| // Pseudo fields.
 | ||||
| 
 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR                     27:24 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_225                 0 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_135                 1 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_315                 2 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_45                  3 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_270                 4 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_90                  5 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_180                 8 | ||||
| #define DE_CONTROL_SHORT_STROKE_DIR_0                   10 | ||||
| #define DE_CONTROL_ROTATION                             25:24 | ||||
| #define DE_CONTROL_ROTATION_0                           0 | ||||
| #define DE_CONTROL_ROTATION_270                         1 | ||||
| #define DE_CONTROL_ROTATION_90                          2 | ||||
| #define DE_CONTROL_ROTATION_180                         3 | ||||
| 
 | ||||
| #define DE_PITCH                                        0x000010 | ||||
| #define DE_PITCH_DESTINATION                            28:16 | ||||
| #define DE_PITCH_SOURCE                                 12:0 | ||||
| 
 | ||||
| #define DE_FOREGROUND                                   0x000014 | ||||
| #define DE_FOREGROUND_COLOR                             31:0 | ||||
| 
 | ||||
| #define DE_BACKGROUND                                   0x000018 | ||||
| #define DE_BACKGROUND_COLOR                             31:0 | ||||
| 
 | ||||
| #define DE_STRETCH_FORMAT                               0x00001C | ||||
| #define DE_STRETCH_FORMAT_PATTERN_XY                    30:30 | ||||
| #define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL             0 | ||||
| #define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE          1 | ||||
| #define DE_STRETCH_FORMAT_PATTERN_Y                     29:27 | ||||
| #define DE_STRETCH_FORMAT_PATTERN_X                     25:23 | ||||
| #define DE_STRETCH_FORMAT_PIXEL_FORMAT                  21:20 | ||||
| #define DE_STRETCH_FORMAT_PIXEL_FORMAT_8                0 | ||||
| #define DE_STRETCH_FORMAT_PIXEL_FORMAT_16               1 | ||||
| #define DE_STRETCH_FORMAT_PIXEL_FORMAT_32               2 | ||||
| #define DE_STRETCH_FORMAT_PIXEL_FORMAT_24               3 | ||||
| 
 | ||||
| #define DE_STRETCH_FORMAT_ADDRESSING                    19:16 | ||||
| #define DE_STRETCH_FORMAT_ADDRESSING_XY                 0 | ||||
| #define DE_STRETCH_FORMAT_ADDRESSING_LINEAR             15 | ||||
| #define DE_STRETCH_FORMAT_SOURCE_HEIGHT                 11:0 | ||||
| 
 | ||||
| #define DE_COLOR_COMPARE                                0x000020 | ||||
| #define DE_COLOR_COMPARE_COLOR                          23:0 | ||||
| 
 | ||||
| #define DE_COLOR_COMPARE_MASK                           0x000024 | ||||
| #define DE_COLOR_COMPARE_MASK_MASKS                     23:0 | ||||
| 
 | ||||
| #define DE_MASKS                                        0x000028 | ||||
| #define DE_MASKS_BYTE_MASK                              31:16 | ||||
| #define DE_MASKS_BIT_MASK                               15:0 | ||||
| 
 | ||||
| #define DE_CLIP_TL                                      0x00002C | ||||
| #define DE_CLIP_TL_TOP                                  31:16 | ||||
| #define DE_CLIP_TL_STATUS                               13:13 | ||||
| #define DE_CLIP_TL_STATUS_DISABLE                       0 | ||||
| #define DE_CLIP_TL_STATUS_ENABLE                        1 | ||||
| #define DE_CLIP_TL_INHIBIT                              12:12 | ||||
| #define DE_CLIP_TL_INHIBIT_OUTSIDE                      0 | ||||
| #define DE_CLIP_TL_INHIBIT_INSIDE                       1 | ||||
| #define DE_CLIP_TL_LEFT                                 11:0 | ||||
| 
 | ||||
| #define DE_CLIP_BR                                      0x000030 | ||||
| #define DE_CLIP_BR_BOTTOM                               31:16 | ||||
| #define DE_CLIP_BR_RIGHT                                12:0 | ||||
| 
 | ||||
| #define DE_MONO_PATTERN_LOW                             0x000034 | ||||
| #define DE_MONO_PATTERN_LOW_PATTERN                     31:0 | ||||
| 
 | ||||
| #define DE_MONO_PATTERN_HIGH                            0x000038 | ||||
| #define DE_MONO_PATTERN_HIGH_PATTERN                    31:0 | ||||
| 
 | ||||
| #define DE_WINDOW_WIDTH                                 0x00003C | ||||
| #define DE_WINDOW_WIDTH_DESTINATION                     28:16 | ||||
| #define DE_WINDOW_WIDTH_SOURCE                          12:0 | ||||
| 
 | ||||
| #define DE_WINDOW_SOURCE_BASE                           0x000040 | ||||
| #define DE_WINDOW_SOURCE_BASE_EXT                       27:27 | ||||
| #define DE_WINDOW_SOURCE_BASE_EXT_LOCAL                 0 | ||||
| #define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL              1 | ||||
| #define DE_WINDOW_SOURCE_BASE_CS                        26:26 | ||||
| #define DE_WINDOW_SOURCE_BASE_CS_0                      0 | ||||
| #define DE_WINDOW_SOURCE_BASE_CS_1                      1 | ||||
| #define DE_WINDOW_SOURCE_BASE_ADDRESS                   25:0 | ||||
| 
 | ||||
| #define DE_WINDOW_DESTINATION_BASE                      0x000044 | ||||
| #define DE_WINDOW_DESTINATION_BASE_EXT                  27:27 | ||||
| #define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL            0 | ||||
| #define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL         1 | ||||
| #define DE_WINDOW_DESTINATION_BASE_CS                   26:26 | ||||
| #define DE_WINDOW_DESTINATION_BASE_CS_0                 0 | ||||
| #define DE_WINDOW_DESTINATION_BASE_CS_1                 1 | ||||
| #define DE_WINDOW_DESTINATION_BASE_ADDRESS              25:0 | ||||
| 
 | ||||
| #define DE_ALPHA                                        0x000048 | ||||
| #define DE_ALPHA_VALUE                                  7:0 | ||||
| 
 | ||||
| #define DE_WRAP                                         0x00004C | ||||
| #define DE_WRAP_X                                       31:16 | ||||
| #define DE_WRAP_Y                                       15:0 | ||||
| 
 | ||||
| #define DE_STATUS                                       0x000050 | ||||
| #define DE_STATUS_CSC                                   1:1 | ||||
| #define DE_STATUS_CSC_CLEAR                             0 | ||||
| #define DE_STATUS_CSC_NOT_ACTIVE                        0 | ||||
| #define DE_STATUS_CSC_ACTIVE                            1 | ||||
| #define DE_STATUS_2D                                    0:0 | ||||
| #define DE_STATUS_2D_CLEAR                              0 | ||||
| #define DE_STATUS_2D_NOT_ACTIVE                         0 | ||||
| #define DE_STATUS_2D_ACTIVE                             1 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* blt direction */ | ||||
| #define TOP_TO_BOTTOM 0 | ||||
| #define LEFT_TO_RIGHT 0 | ||||
| #define BOTTOM_TO_TOP 1 | ||||
| #define RIGHT_TO_LEFT 1 | ||||
| 
 | ||||
| void hw_set2dformat(struct lynx_accel * accel,int fmt); | ||||
| 
 | ||||
| void hw_de_init(struct lynx_accel * accel); | ||||
| 
 | ||||
| int hw_fillrect(struct lynx_accel * accel, | ||||
| 				u32 base,u32 pitch,u32 Bpp, | ||||
| 				u32 x,u32 y,u32 width,u32 height, | ||||
| 				u32 color,u32 rop); | ||||
| 
 | ||||
| int hw_copyarea( | ||||
| struct lynx_accel * accel, | ||||
| unsigned int sBase,  /* Address of source: offset in frame buffer */ | ||||
| unsigned int sPitch, /* Pitch value of source surface in BYTE */ | ||||
| unsigned int sx, | ||||
| unsigned int sy,     /* Starting coordinate of source surface */ | ||||
| unsigned int dBase,  /* Address of destination: offset in frame buffer */ | ||||
| unsigned int dPitch, /* Pitch value of destination surface in BYTE */ | ||||
| unsigned int bpp,    /* Color depth of destination surface */ | ||||
| unsigned int dx, | ||||
| unsigned int dy,     /* Starting coordinate of destination surface */ | ||||
| unsigned int width, | ||||
| unsigned int height, /* width and height of rectangle in pixel value */ | ||||
| unsigned int rop2); | ||||
| 
 | ||||
| int hw_imageblit( | ||||
| struct lynx_accel * accel, | ||||
| unsigned char *pSrcbuf, /* pointer to start of source buffer in system memory */ | ||||
| int srcDelta,          /* Pitch value (in bytes) of the source buffer, +ive means top down and -ive mean button up */ | ||||
| unsigned int startBit, /* Mono data can start at any bit in a byte, this value should be 0 to 7 */ | ||||
| unsigned int dBase,    /* Address of destination: offset in frame buffer */ | ||||
| unsigned int dPitch,   /* Pitch value of destination surface in BYTE */ | ||||
| unsigned int bytePerPixel,      /* Color depth of destination surface */ | ||||
| unsigned int dx, | ||||
| unsigned int dy,       /* Starting coordinate of destination surface */ | ||||
| unsigned int width, | ||||
| unsigned int height,   /* width and height of rectange in pixel value */ | ||||
| unsigned int fColor,   /* Foreground color (corresponding to a 1 in the monochrome data */ | ||||
| unsigned int bColor,   /* Background color (corresponding to a 0 in the monochrome data */ | ||||
| unsigned int rop2); | ||||
| #endif | ||||
							
								
								
									
										254
									
								
								drivers/staging/sm750fb/sm750_cursor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								drivers/staging/sm750fb/sm750_cursor.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,254 @@ | ||||
| #include<linux/module.h> | ||||
| #include<linux/kernel.h> | ||||
| #include<linux/errno.h> | ||||
| #include<linux/string.h> | ||||
| #include<linux/mm.h> | ||||
| #include<linux/slab.h> | ||||
| #include<linux/delay.h> | ||||
| #include<linux/fb.h> | ||||
| #include<linux/ioport.h> | ||||
| #include<linux/init.h> | ||||
| #include<linux/pci.h> | ||||
| #include<linux/vmalloc.h> | ||||
| #include<linux/pagemap.h> | ||||
| #include <linux/console.h> | ||||
| #include<linux/platform_device.h> | ||||
| #include<linux/screen_info.h> | ||||
| 
 | ||||
| #include "sm750.h" | ||||
| #include "sm750_help.h" | ||||
| #include "sm750_cursor.h" | ||||
| 
 | ||||
| 
 | ||||
| #define PEEK32(addr) \ | ||||
| readl(cursor->mmio + (addr)) | ||||
| 
 | ||||
| #define POKE32(addr,data) \ | ||||
| writel((data),cursor->mmio + (addr)) | ||||
| 
 | ||||
| /* cursor control for voyager and 718/750*/ | ||||
| #define HWC_ADDRESS                         0x0 | ||||
| #define HWC_ADDRESS_ENABLE                  31:31 | ||||
| #define HWC_ADDRESS_ENABLE_DISABLE          0 | ||||
| #define HWC_ADDRESS_ENABLE_ENABLE           1 | ||||
| #define HWC_ADDRESS_EXT                     27:27 | ||||
| #define HWC_ADDRESS_EXT_LOCAL               0 | ||||
| #define HWC_ADDRESS_EXT_EXTERNAL            1 | ||||
| #define HWC_ADDRESS_CS                      26:26 | ||||
| #define HWC_ADDRESS_CS_0                    0 | ||||
| #define HWC_ADDRESS_CS_1                    1 | ||||
| #define HWC_ADDRESS_ADDRESS                 25:0 | ||||
| 
 | ||||
| #define HWC_LOCATION                        0x4 | ||||
| #define HWC_LOCATION_TOP                    27:27 | ||||
| #define HWC_LOCATION_TOP_INSIDE             0 | ||||
| #define HWC_LOCATION_TOP_OUTSIDE            1 | ||||
| #define HWC_LOCATION_Y                      26:16 | ||||
| #define HWC_LOCATION_LEFT                   11:11 | ||||
| #define HWC_LOCATION_LEFT_INSIDE            0 | ||||
| #define HWC_LOCATION_LEFT_OUTSIDE           1 | ||||
| #define HWC_LOCATION_X                      10:0 | ||||
| 
 | ||||
| #define HWC_COLOR_12                        0x8 | ||||
| #define HWC_COLOR_12_2_RGB565               31:16 | ||||
| #define HWC_COLOR_12_1_RGB565               15:0 | ||||
| 
 | ||||
| #define HWC_COLOR_3                         0xC | ||||
| #define HWC_COLOR_3_RGB565                  15:0 | ||||
| 
 | ||||
| 
 | ||||
| /* hw_cursor_xxx works for voyager,718 and 750 */ | ||||
| void hw_cursor_enable(struct lynx_cursor * cursor) | ||||
| { | ||||
| 	u32 reg; | ||||
| 	reg = FIELD_VALUE(0,HWC_ADDRESS,ADDRESS,cursor->offset)| | ||||
| 			FIELD_SET(0,HWC_ADDRESS,EXT,LOCAL)| | ||||
| 			FIELD_SET(0,HWC_ADDRESS,ENABLE,ENABLE); | ||||
| 	POKE32(HWC_ADDRESS,reg); | ||||
| } | ||||
| void hw_cursor_disable(struct lynx_cursor * cursor) | ||||
| { | ||||
| 	POKE32(HWC_ADDRESS,0); | ||||
| } | ||||
| 
 | ||||
| void hw_cursor_setSize(struct lynx_cursor * cursor, | ||||
| 						int w,int h) | ||||
| { | ||||
| 	cursor->w = w; | ||||
| 	cursor->h = h; | ||||
| } | ||||
| void hw_cursor_setPos(struct lynx_cursor * cursor, | ||||
| 						int x,int y) | ||||
| { | ||||
| 	u32 reg; | ||||
| 	reg = FIELD_VALUE(0,HWC_LOCATION,Y,y)| | ||||
| 			FIELD_VALUE(0,HWC_LOCATION,X,x); | ||||
| 	POKE32(HWC_LOCATION,reg); | ||||
| } | ||||
| void hw_cursor_setColor(struct lynx_cursor * cursor, | ||||
| 						u32 fg,u32 bg) | ||||
| { | ||||
| 	POKE32(HWC_COLOR_12,(fg<<16)|(bg&0xffff)); | ||||
| 	POKE32(HWC_COLOR_3,0xffe0); | ||||
| } | ||||
| 
 | ||||
| void hw_cursor_setData(struct lynx_cursor * cursor, | ||||
| 			u16 rop,const u8* pcol,const u8* pmsk) | ||||
| { | ||||
| 	int i,j,count,pitch,offset; | ||||
| 	u8 color,mask,opr; | ||||
| 	u16 data; | ||||
| 	u16 * pbuffer,*pstart; | ||||
| 	static ulong odd = 0; | ||||
| 
 | ||||
| 	/*  in byte*/ | ||||
| 	pitch = cursor->w >> 3; | ||||
| 
 | ||||
| 	/* in byte	*/ | ||||
| 	count = pitch * cursor->h; | ||||
| 
 | ||||
| 	/* in ushort */ | ||||
| 	offset = cursor->maxW * 2 / 8 / 2; | ||||
| 
 | ||||
| 	data = 0; | ||||
| 	pstart = (u16 *)cursor->vstart; | ||||
| 	pbuffer = pstart; | ||||
| 
 | ||||
| /*
 | ||||
| 	if(odd &1){ | ||||
| 		hw_cursor_setData2(cursor,rop,pcol,pmsk); | ||||
| 	} | ||||
| 	odd++; | ||||
| 	if(odd > 0xfffffff0) | ||||
| 		odd=0; | ||||
| */ | ||||
| 
 | ||||
| 	for(i=0;i<count;i++) | ||||
| 	{ | ||||
| 		color = *pcol++; | ||||
| 		mask = *pmsk++; | ||||
| 		data = 0; | ||||
| 
 | ||||
| 		/* either method below works well,
 | ||||
| 		 * but method 2 shows no lag | ||||
| 		 * and method 1 seems a bit wrong*/ | ||||
| #if 0 | ||||
| 		if(rop == ROP_XOR) | ||||
| 			opr = mask ^ color; | ||||
| 		else | ||||
| 			opr = mask & color; | ||||
| 
 | ||||
| 		for(j=0;j<8;j++) | ||||
| 		{ | ||||
| 
 | ||||
| 			if(opr & (0x80 >> j)) | ||||
| 			{	//use fg color,id = 2
 | ||||
| 				data |= 2 << (j*2); | ||||
| 			}else{ | ||||
| 				//use bg color,id = 1
 | ||||
| 				data |= 1 << (j*2); | ||||
| 			} | ||||
| 		} | ||||
| #else | ||||
| 		for(j=0;j<8;j++){ | ||||
| 			if(mask & (0x80>>j)){ | ||||
| 				if(rop == ROP_XOR) | ||||
| 					opr = mask ^ color; | ||||
| 				else | ||||
| 					opr = mask & color; | ||||
| 
 | ||||
| 				/* 2 stands for forecolor and 1 for backcolor */ | ||||
| 				data |= ((opr & (0x80>>j))?2:1)<<(j*2); | ||||
| 			} | ||||
| 		} | ||||
| #endif | ||||
| 		*pbuffer = data; | ||||
| 
 | ||||
| 		/* assume pitch is 1,2,4,8,...*/ | ||||
| #if 0 | ||||
| 		if(!((i+1)&(pitch-1)))   /* below line equal to is line */ | ||||
| #else | ||||
| 		if((i+1) % pitch == 0) | ||||
| #endif | ||||
| 		{ | ||||
| 			/* need a return */ | ||||
| 			pstart += offset; | ||||
| 			pbuffer = pstart; | ||||
| 		}else{ | ||||
| 			pbuffer++; | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void hw_cursor_setData2(struct lynx_cursor * cursor, | ||||
| 			u16 rop,const u8* pcol,const u8* pmsk) | ||||
| { | ||||
| 	int i,j,count,pitch,offset; | ||||
| 	u8 color,mask,opr; | ||||
| 	u16 data; | ||||
| 	u16 * pbuffer,*pstart; | ||||
| 
 | ||||
| 	/*  in byte*/ | ||||
| 	pitch = cursor->w >> 3; | ||||
| 
 | ||||
| 	/* in byte	*/ | ||||
| 	count = pitch * cursor->h; | ||||
| 
 | ||||
| 	/* in ushort */ | ||||
| 	offset = cursor->maxW * 2 / 8 / 2; | ||||
| 
 | ||||
| 	data = 0; | ||||
| 	pstart = (u16 *)cursor->vstart; | ||||
| 	pbuffer = pstart; | ||||
| 
 | ||||
| 	for(i=0;i<count;i++) | ||||
| 	{ | ||||
| 		color = *pcol++; | ||||
| 		mask = *pmsk++; | ||||
| 		data = 0; | ||||
| 
 | ||||
| 		/* either method below works well, but method 2 shows no lag */ | ||||
| #if 0 | ||||
| 		if(rop == ROP_XOR) | ||||
| 			opr = mask ^ color; | ||||
| 		else | ||||
| 			opr = mask & color; | ||||
| 
 | ||||
| 		for(j=0;j<8;j++) | ||||
| 		{ | ||||
| 
 | ||||
| 			if(opr & (0x80 >> j)) | ||||
| 			{	//use fg color,id = 2
 | ||||
| 				data |= 2 << (j*2); | ||||
| 			}else{ | ||||
| 				//use bg color,id = 1
 | ||||
| 				data |= 1 << (j*2); | ||||
| 			} | ||||
| 		} | ||||
| #else | ||||
| 		for(j=0;j<8;j++){ | ||||
| 			if(mask & (1<<j)) | ||||
| 				data |= ((color & (1<<j))?1:2)<<(j*2); | ||||
| 		} | ||||
| #endif | ||||
| 		*pbuffer = data; | ||||
| 
 | ||||
| 		/* assume pitch is 1,2,4,8,...*/ | ||||
| 		if(!(i&(pitch-1))) | ||||
| 		//if((i+1) % pitch == 0)
 | ||||
| 		{ | ||||
| 			/* need a return */ | ||||
| 			pstart += offset; | ||||
| 			pbuffer = pstart; | ||||
| 		}else{ | ||||
| 			pbuffer++; | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 	return 0; | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										17
									
								
								drivers/staging/sm750fb/sm750_cursor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								drivers/staging/sm750fb/sm750_cursor.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| #ifndef LYNX_CURSOR_H__ | ||||
| #define LYNX_CURSOR_H__ | ||||
| 
 | ||||
| /* hw_cursor_xxx works for voyager,718 and 750 */ | ||||
| void hw_cursor_enable(struct lynx_cursor * cursor); | ||||
| void hw_cursor_disable(struct lynx_cursor * cursor); | ||||
| void hw_cursor_setSize(struct lynx_cursor * cursor, | ||||
| 						int w,int h); | ||||
| void hw_cursor_setPos(struct lynx_cursor * cursor, | ||||
| 						int x,int y); | ||||
| void hw_cursor_setColor(struct lynx_cursor * cursor, | ||||
| 						u32 fg,u32 bg); | ||||
| void hw_cursor_setData(struct lynx_cursor * cursor, | ||||
| 			u16 rop,const u8* data,const u8* mask); | ||||
| void hw_cursor_setData2(struct lynx_cursor * cursor, | ||||
| 			u16 rop,const u8* data,const u8* mask); | ||||
| #endif | ||||
							
								
								
									
										111
									
								
								drivers/staging/sm750fb/sm750_help.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								drivers/staging/sm750fb/sm750_help.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| #ifndef LYNX_HELP_H__ | ||||
| #define LYNX_HELP_H__ | ||||
| /*****************************************************************************\
 | ||||
|  *                                FIELD MACROS                               * | ||||
| \*****************************************************************************/ | ||||
| 
 | ||||
| #define _LSB(f)             (0 ? f) | ||||
| #define _MSB(f)             (1 ? f) | ||||
| #define _COUNT(f)           (_MSB(f) - _LSB(f) + 1) | ||||
| 
 | ||||
| #define RAW_MASK(f)         (0xFFFFFFFF >> (32 - _COUNT(f))) | ||||
| #define GET_MASK(f)         (RAW_MASK(f) << _LSB(f)) | ||||
| #define GET_FIELD(d,f)      (((d) >> _LSB(f)) & RAW_MASK(f)) | ||||
| #define TEST_FIELD(d,f,v)   (GET_FIELD(d,f) == f ## _ ## v) | ||||
| #define SET_FIELD(d,f,v)    (((d) & ~GET_MASK(f)) | \ | ||||
|                             (((f ## _ ## v) & RAW_MASK(f)) << _LSB(f))) | ||||
| #define SET_FIELDV(d,f,v)   (((d) & ~GET_MASK(f)) | \ | ||||
|                             (((v) & RAW_MASK(f)) << _LSB(f))) | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| //                                                                            //
 | ||||
| // Internal macros                                                            //
 | ||||
| //                                                                            //
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #define _F_START(f)             (0 ? f) | ||||
| #define _F_END(f)               (1 ? f) | ||||
| #define _F_SIZE(f)              (1 + _F_END(f) - _F_START(f)) | ||||
| #define _F_MASK(f)              (((1 << _F_SIZE(f)) - 1) << _F_START(f)) | ||||
| #define _F_NORMALIZE(v, f)      (((v) & _F_MASK(f)) >> _F_START(f)) | ||||
| #define _F_DENORMALIZE(v, f)    (((v) << _F_START(f)) & _F_MASK(f)) | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| //                                                                            //
 | ||||
| // Global macros                                                              //
 | ||||
| //                                                                            //
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #define FIELD_GET(x, reg, field) \ | ||||
| ( \ | ||||
|     _F_NORMALIZE((x), reg ## _ ## field) \ | ||||
| ) | ||||
| 
 | ||||
| #define FIELD_SET(x, reg, field, value) \ | ||||
| ( \ | ||||
|     (x & ~_F_MASK(reg ## _ ## field)) \ | ||||
|     | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \ | ||||
| ) | ||||
| 
 | ||||
| #define FIELD_VALUE(x, reg, field, value) \ | ||||
| ( \ | ||||
|     (x & ~_F_MASK(reg ## _ ## field)) \ | ||||
|     | _F_DENORMALIZE(value, reg ## _ ## field) \ | ||||
| ) | ||||
| 
 | ||||
| #define FIELD_CLEAR(reg, field) \ | ||||
| ( \ | ||||
|     ~ _F_MASK(reg ## _ ## field) \ | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| //                                                                            //
 | ||||
| // Field Macros                                                               //
 | ||||
| //                                                                            //
 | ||||
| ////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #define FIELD_START(field)              (0 ? field) | ||||
| #define FIELD_END(field)                (1 ? field) | ||||
| #define FIELD_SIZE(field)               (1 + FIELD_END(field) - FIELD_START(field)) | ||||
| #define FIELD_MASK(field)               (((1 << (FIELD_SIZE(field)-1)) | ((1 << (FIELD_SIZE(field)-1)) - 1)) << FIELD_START(field)) | ||||
| #define FIELD_NORMALIZE(reg, field)     (((reg) & FIELD_MASK(field)) >> FIELD_START(field)) | ||||
| #define FIELD_DENORMALIZE(field, value) (((value) << FIELD_START(field)) & FIELD_MASK(field)) | ||||
| 
 | ||||
| #define FIELD_INIT(reg, field, value)   FIELD_DENORMALIZE(reg ## _ ## field, \ | ||||
|                                                           reg ## _ ## field ## _ ## value) | ||||
| #define FIELD_INIT_VAL(reg, field, value) \ | ||||
|                                         (FIELD_DENORMALIZE(reg ## _ ## field, value)) | ||||
| #define FIELD_VAL_SET(x, r, f, v)       x = x & ~FIELD_MASK(r ## _ ## f) \ | ||||
|                                               | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) | ||||
| 
 | ||||
| #define RGB(r, g, b) \ | ||||
| ( \ | ||||
|     (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \ | ||||
| ) | ||||
| 
 | ||||
| #define RGB16(r, g, b) \ | ||||
| ( \ | ||||
|     (unsigned short) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3)) \ | ||||
| ) | ||||
| 
 | ||||
| static inline unsigned int absDiff(unsigned int a,unsigned int b) | ||||
| { | ||||
| 	if(a<b) | ||||
| 		return b-a; | ||||
| 	else | ||||
| 		return a-b; | ||||
| } | ||||
| 
 | ||||
| /* n / d + 1 / 2 = (2n + d) / 2d */ | ||||
| #define roundedDiv(num,denom)	((2 * (num) + (denom)) / (2 * (denom))) | ||||
| #define MB(x) ((x)<<20) | ||||
| #define KB(x) ((x)<<10) | ||||
| #define MHz(x) ((x) * 1000000) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										640
									
								
								drivers/staging/sm750fb/sm750_hw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										640
									
								
								drivers/staging/sm750fb/sm750_hw.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,640 @@ | ||||
| #include <linux/version.h> | ||||
| #include<linux/module.h> | ||||
| #include<linux/kernel.h> | ||||
| #include<linux/errno.h> | ||||
| #include<linux/string.h> | ||||
| #include<linux/mm.h> | ||||
| #include<linux/slab.h> | ||||
| #include<linux/delay.h> | ||||
| #include<linux/fb.h> | ||||
| #include<linux/ioport.h> | ||||
| #include<linux/init.h> | ||||
| #include<linux/pci.h> | ||||
| #include<linux/vmalloc.h> | ||||
| #include<linux/pagemap.h> | ||||
| #include <linux/console.h> | ||||
| #ifdef CONFIG_MTRR | ||||
| #include <asm/mtrr.h> | ||||
| #endif | ||||
| #include<linux/platform_device.h> | ||||
| #include<linux/screen_info.h> | ||||
| 
 | ||||
| #include "sm750.h" | ||||
| #include "sm750_hw.h" | ||||
| #include "ddk750.h" | ||||
| #include "sm750_accel.h" | ||||
| 
 | ||||
| int hw_sm750_map(struct lynx_share* share,struct pci_dev* pdev) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct sm750_share * spec_share; | ||||
| 	 | ||||
| 
 | ||||
| 	spec_share = container_of(share,struct sm750_share,share); | ||||
| 	ret = 0; | ||||
| 
 | ||||
| 	share->vidreg_start  = pci_resource_start(pdev,1); | ||||
| 	share->vidreg_size = MB(2); | ||||
| 
 | ||||
| 	pr_info("mmio phyAddr = %x\n",share->vidreg_start); | ||||
| 
 | ||||
| 	/* reserve the vidreg space of smi adaptor
 | ||||
| 	 * if you do this, u need to add release region code | ||||
| 	 * in lynxfb_remove, or memory will not be mapped again | ||||
| 	 * successfully | ||||
| 	 * */ | ||||
| 
 | ||||
| 	if((ret = pci_request_region(pdev,1,"sm750fb"))) | ||||
| 	{ | ||||
| 		pr_err("Can not request PCI regions.\n"); | ||||
| 		goto exit; | ||||
| 	} | ||||
| 
 | ||||
| 	/* now map mmio and vidmem*/ | ||||
| 	share->pvReg = ioremap_nocache(share->vidreg_start,share->vidreg_size); | ||||
| 	if(!share->pvReg){ | ||||
| 		pr_err("mmio failed\n"); | ||||
| 		ret = -EFAULT; | ||||
| 		goto exit; | ||||
| 	}else{ | ||||
| 		pr_info("mmio virtual addr = %p\n",share->pvReg); | ||||
| 	} | ||||
| 
 | ||||
| 	 | ||||
| 	share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1; | ||||
| 	share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1; | ||||
| 
 | ||||
| 	ddk750_set_mmio(share->pvReg,share->devid,share->revid); | ||||
| 
 | ||||
| 	share->vidmem_start = pci_resource_start(pdev,0); | ||||
| 	/* don't use pdev_resource[x].end - resource[x].start to
 | ||||
| 	 * calculate the resource size,its only the maximum available | ||||
| 	 * size but not the actual size,use | ||||
| 	 * @hw_sm750_getVMSize function can be safe. | ||||
| 	 * */ | ||||
| 	share->vidmem_size = hw_sm750_getVMSize(share); | ||||
| 	pr_info("video memory phyAddr = %x, size = %d bytes\n", | ||||
| 	share->vidmem_start,share->vidmem_size); | ||||
| 
 | ||||
| 	/* reserve the vidmem space of smi adaptor */ | ||||
| #if 0 | ||||
| 	if((ret = pci_request_region(pdev,0,_moduleName_))) | ||||
| 	{ | ||||
| 		pr_err("Can not request PCI regions.\n"); | ||||
| 		goto exit; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	share->pvMem = ioremap(share->vidmem_start, | ||||
| 							share->vidmem_size); | ||||
| 
 | ||||
| 	if(!share->pvMem){ | ||||
| 		pr_err("Map video memory failed\n"); | ||||
| 		ret = -EFAULT; | ||||
| 		goto exit; | ||||
| 	}else{ | ||||
| 		pr_info("video memory vaddr = %p\n",share->pvMem); | ||||
| 	} | ||||
| exit: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int hw_sm750_inithw(struct lynx_share* share,struct pci_dev * pdev) | ||||
| { | ||||
| 	struct sm750_share * spec_share; | ||||
| 	struct init_status * parm; | ||||
| 	 | ||||
| 	spec_share = container_of(share,struct sm750_share,share); | ||||
| 	parm = &spec_share->state.initParm; | ||||
| 	if(parm->chip_clk == 0) | ||||
| 		parm->chip_clk = (getChipType() == SM750LE)? | ||||
| 						DEFAULT_SM750LE_CHIP_CLOCK : | ||||
| 						DEFAULT_SM750_CHIP_CLOCK; | ||||
| 
 | ||||
| 	if(parm->mem_clk == 0) | ||||
| 		parm->mem_clk = parm->chip_clk; | ||||
| 	if(parm->master_clk == 0) | ||||
| 		parm->master_clk = parm->chip_clk/3; | ||||
| 
 | ||||
| 	ddk750_initHw((initchip_param_t *)&spec_share->state.initParm); | ||||
| 	/* for sm718,open pci burst */ | ||||
| 	if(share->devid == 0x718){ | ||||
| 		POKE32(SYSTEM_CTRL, | ||||
| 				FIELD_SET(PEEK32(SYSTEM_CTRL),SYSTEM_CTRL,PCI_BURST,ON)); | ||||
| 	} | ||||
| 
 | ||||
| 	/* sm750 use sii164, it can be setup with default value
 | ||||
| 	 * by on power, so initDVIDisp can be skipped */ | ||||
| #if 0 | ||||
| 	ddk750_initDVIDisp(); | ||||
| #endif | ||||
| 
 | ||||
| 	if(getChipType() != SM750LE) | ||||
| 	{ | ||||
| 		/* does user need CRT ?*/ | ||||
| 		if(spec_share->state.nocrt){ | ||||
| 			POKE32(MISC_CTRL, | ||||
| 					FIELD_SET(PEEK32(MISC_CTRL), | ||||
| 					MISC_CTRL, | ||||
| 					DAC_POWER,OFF)); | ||||
| 			/* shut off dpms */ | ||||
| 			POKE32(SYSTEM_CTRL, | ||||
| 					FIELD_SET(PEEK32(SYSTEM_CTRL), | ||||
| 					SYSTEM_CTRL, | ||||
| 					DPMS,VNHN)); | ||||
| 		}else{ | ||||
| 			POKE32(MISC_CTRL, | ||||
| 					FIELD_SET(PEEK32(MISC_CTRL), | ||||
| 					MISC_CTRL, | ||||
| 					DAC_POWER,ON)); | ||||
| 			/* turn on dpms */ | ||||
| 			POKE32(SYSTEM_CTRL, | ||||
| 					FIELD_SET(PEEK32(SYSTEM_CTRL), | ||||
| 					SYSTEM_CTRL, | ||||
| 					DPMS,VPHP)); | ||||
| 		} | ||||
| 
 | ||||
| 		switch (spec_share->state.pnltype){ | ||||
| 			case sm750_doubleTFT: | ||||
| 			case sm750_24TFT: | ||||
| 			case sm750_dualTFT: | ||||
| 			POKE32(PANEL_DISPLAY_CTRL, | ||||
| 				FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), | ||||
| 							PANEL_DISPLAY_CTRL, | ||||
| 							TFT_DISP, | ||||
| 							spec_share->state.pnltype)); | ||||
| 			break; | ||||
| 		} | ||||
| 	}else{ | ||||
| 		/* for 750LE ,no DVI chip initilization makes Monitor no signal */ | ||||
| 		/* Set up GPIO for software I2C to program DVI chip in the
 | ||||
| 		   Xilinx SP605 board, in order to have video signal. | ||||
| 		 */ | ||||
|         swI2CInit(0,1); | ||||
| 
 | ||||
| 
 | ||||
|         /* Customer may NOT use CH7301 DVI chip, which has to be
 | ||||
|            initialized differently. | ||||
|          */ | ||||
|         if (swI2CReadReg(0xec, 0x4a) == 0x95) | ||||
|         { | ||||
|             /* The following register values for CH7301 are from
 | ||||
|                Chrontel app note and our experiment. | ||||
|              */ | ||||
| 			pr_info("yes,CH7301 DVI chip found\n"); | ||||
|             swI2CWriteReg(0xec, 0x1d, 0x16); | ||||
|             swI2CWriteReg(0xec, 0x21, 0x9); | ||||
|             swI2CWriteReg(0xec, 0x49, 0xC0); | ||||
| 			pr_info("okay,CH7301 DVI chip setup done\n"); | ||||
|         } | ||||
| 	} | ||||
| 
 | ||||
| 	/* init 2d engine */ | ||||
| 	if(!share->accel_off){ | ||||
| 		hw_sm750_initAccel(share); | ||||
| //		share->accel.de_wait = hw_sm750_deWait;
 | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| resource_size_t hw_sm750_getVMSize(struct lynx_share * share) | ||||
| { | ||||
| 	resource_size_t ret; | ||||
| 	 | ||||
| 	ret = ddk750_getVMSize(); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| int hw_sm750_output_checkMode(struct lynxfb_output* output,struct fb_var_screeninfo* var) | ||||
| { | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int hw_sm750_output_setMode(struct lynxfb_output* output, | ||||
| 									struct fb_var_screeninfo* var,struct fb_fix_screeninfo* fix) | ||||
| { | ||||
| 	int ret; | ||||
| 	disp_output_t dispSet; | ||||
| 	int channel; | ||||
| 	 | ||||
| 	ret = 0; | ||||
| 	dispSet = 0; | ||||
| 	channel = *output->channel; | ||||
| 
 | ||||
| 
 | ||||
| 	if(getChipType() != SM750LE){ | ||||
| 		if(channel == sm750_primary){ | ||||
| 			pr_info("primary channel\n"); | ||||
| 			if(output->paths & sm750_panel) | ||||
| 				dispSet |= do_LCD1_PRI; | ||||
| 			if(output->paths & sm750_crt) | ||||
| 				dispSet |= do_CRT_PRI; | ||||
| 
 | ||||
| 		}else{ | ||||
| 			pr_info("secondary channel\n"); | ||||
| 			if(output->paths & sm750_panel) | ||||
| 				dispSet |= do_LCD1_SEC; | ||||
| 			if(output->paths & sm750_crt) | ||||
| 				dispSet |= do_CRT_SEC; | ||||
| 
 | ||||
| 		} | ||||
| 		ddk750_setLogicalDispOut(dispSet); | ||||
| 	}else{ | ||||
| 		/* just open DISPLAY_CONTROL_750LE register bit 3:0*/ | ||||
| 		u32 reg; | ||||
| 		reg = PEEK32(DISPLAY_CONTROL_750LE); | ||||
| 		reg |= 0xf; | ||||
| 		POKE32(DISPLAY_CONTROL_750LE,reg); | ||||
| 	} | ||||
| 
 | ||||
| 	pr_info("ddk setlogicdispout done \n"); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void hw_sm750_output_clear(struct lynxfb_output* output) | ||||
| { | ||||
| 	 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| int hw_sm750_crtc_checkMode(struct lynxfb_crtc* crtc,struct fb_var_screeninfo* var) | ||||
| { | ||||
| 	struct lynx_share * share; | ||||
| 	 | ||||
| 
 | ||||
| 	share = container_of(crtc,struct lynxfb_par,crtc)->share; | ||||
| 
 | ||||
| 	switch (var->bits_per_pixel){ | ||||
| 		case 8: | ||||
| 		case 16: | ||||
| 			break; | ||||
| 		case 32: | ||||
| 			if(share->revid == (unsigned char)SM750LE_REVISION_ID){ | ||||
| 				pr_debug("750le do not support 32bpp\n"); | ||||
| 				return -EINVAL; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			return -EINVAL; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| 	set the controller's mode for @crtc charged with @var and @fix parameters | ||||
| */ | ||||
| int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc, | ||||
| 								struct fb_var_screeninfo* var, | ||||
| 								struct fb_fix_screeninfo* fix) | ||||
| { | ||||
| 	int ret,fmt; | ||||
| 	u32 reg; | ||||
| 	mode_parameter_t modparm; | ||||
| 	clock_type_t clock; | ||||
| 	struct lynx_share * share; | ||||
| 	struct lynxfb_par * par; | ||||
| 
 | ||||
| 	 | ||||
| 	ret = 0; | ||||
| 	par = container_of(crtc,struct lynxfb_par,crtc); | ||||
| 	share = par->share; | ||||
| #if 1 | ||||
| 	if(!share->accel_off){ | ||||
| 		/* set 2d engine pixel format according to mode bpp */ | ||||
| 		switch(var->bits_per_pixel){ | ||||
| 			case 8: | ||||
| 				fmt = 0; | ||||
| 				break; | ||||
| 			case 16: | ||||
| 				fmt = 1; | ||||
| 				break; | ||||
| 			case 32: | ||||
| 			default: | ||||
| 				fmt = 2; | ||||
| 				break; | ||||
| 		} | ||||
| 		hw_set2dformat(&share->accel,fmt); | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	/* set timing */ | ||||
| //	modparm.pixel_clock = PS_TO_HZ(var->pixclock);
 | ||||
| 	modparm.pixel_clock = ps_to_hz(var->pixclock); | ||||
| 	modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG; | ||||
| 	modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG; | ||||
| 	modparm.clock_phase_polarity = (var->sync& FB_SYNC_COMP_HIGH_ACT) ? POS:NEG; | ||||
| 	modparm.horizontal_display_end = var->xres; | ||||
| 	modparm.horizontal_sync_width = var->hsync_len; | ||||
| 	modparm.horizontal_sync_start = var->xres + var->right_margin; | ||||
| 	modparm.horizontal_total = var->xres + var->left_margin + var->right_margin + var->hsync_len; | ||||
| 	modparm.vertical_display_end = var->yres; | ||||
| 	modparm.vertical_sync_height = var->vsync_len; | ||||
| 	modparm.vertical_sync_start = var->yres + var->lower_margin; | ||||
| 	modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; | ||||
| 
 | ||||
| 	/* choose pll */ | ||||
| 	if(crtc->channel != sm750_secondary) | ||||
| 		clock = PRIMARY_PLL; | ||||
| 	else | ||||
| 		clock = SECONDARY_PLL; | ||||
| 
 | ||||
| 	pr_debug("Request pixel clock = %lu\n",modparm.pixel_clock); | ||||
| 	ret = ddk750_setModeTiming(&modparm,clock); | ||||
| 	if(ret){ | ||||
| 		pr_err("Set mode timing failed\n"); | ||||
| 		goto exit; | ||||
| 	} | ||||
| 
 | ||||
| 	if(crtc->channel != sm750_secondary){ | ||||
| 		/* set pitch, offset ,width,start address ,etc... */ | ||||
| 		POKE32(PANEL_FB_ADDRESS, | ||||
| 			FIELD_SET(0,PANEL_FB_ADDRESS,STATUS,CURRENT)| | ||||
| 			FIELD_SET(0,PANEL_FB_ADDRESS,EXT,LOCAL)| | ||||
| 			FIELD_VALUE(0,PANEL_FB_ADDRESS,ADDRESS,crtc->oScreen)); | ||||
| 
 | ||||
| 		reg = var->xres * (var->bits_per_pixel >> 3); | ||||
| 		/* crtc->channel is not equal to par->index on numeric,be aware of that */ | ||||
| 		reg = PADDING(crtc->line_pad,reg); | ||||
| 
 | ||||
| 		POKE32(PANEL_FB_WIDTH, | ||||
| 			FIELD_VALUE(0,PANEL_FB_WIDTH,WIDTH,reg)| | ||||
| 			FIELD_VALUE(0,PANEL_FB_WIDTH,OFFSET,fix->line_length)); | ||||
| 
 | ||||
| 		POKE32(PANEL_WINDOW_WIDTH, | ||||
| 			FIELD_VALUE(0,PANEL_WINDOW_WIDTH,WIDTH,var->xres -1)| | ||||
| 			FIELD_VALUE(0,PANEL_WINDOW_WIDTH,X,var->xoffset)); | ||||
| 
 | ||||
| 		POKE32(PANEL_WINDOW_HEIGHT, | ||||
| 			FIELD_VALUE(0,PANEL_WINDOW_HEIGHT,HEIGHT,var->yres_virtual - 1)| | ||||
| 			FIELD_VALUE(0,PANEL_WINDOW_HEIGHT,Y,var->yoffset)); | ||||
| 
 | ||||
| 		POKE32(PANEL_PLANE_TL,0); | ||||
| 
 | ||||
| 		POKE32(PANEL_PLANE_BR, | ||||
| 			FIELD_VALUE(0,PANEL_PLANE_BR,BOTTOM,var->yres - 1)| | ||||
| 			FIELD_VALUE(0,PANEL_PLANE_BR,RIGHT,var->xres - 1)); | ||||
| 
 | ||||
| 		/* set pixel format */ | ||||
| 		reg = PEEK32(PANEL_DISPLAY_CTRL); | ||||
| 		POKE32(PANEL_DISPLAY_CTRL, | ||||
| 			FIELD_VALUE(reg, | ||||
| 			PANEL_DISPLAY_CTRL,FORMAT, | ||||
| 			(var->bits_per_pixel >> 4) | ||||
| 			)); | ||||
| 	}else{ | ||||
| 		/* not implemented now */ | ||||
| 		POKE32(CRT_FB_ADDRESS,crtc->oScreen); | ||||
| 		reg = var->xres * (var->bits_per_pixel >> 3); | ||||
| 		/* crtc->channel is not equal to par->index on numeric,be aware of that */ | ||||
| 		reg = PADDING(crtc->line_pad,reg); | ||||
| 
 | ||||
| 		POKE32(CRT_FB_WIDTH, | ||||
| 			FIELD_VALUE(0,CRT_FB_WIDTH,WIDTH,reg)| | ||||
| 			FIELD_VALUE(0,CRT_FB_WIDTH,OFFSET,fix->line_length)); | ||||
| 
 | ||||
| 		/* SET PIXEL FORMAT */ | ||||
| 		reg = PEEK32(CRT_DISPLAY_CTRL); | ||||
| 		reg = FIELD_VALUE(reg,CRT_DISPLAY_CTRL,FORMAT,var->bits_per_pixel >> 4); | ||||
| 		POKE32(CRT_DISPLAY_CTRL,reg); | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| exit: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void hw_sm750_crtc_clear(struct lynxfb_crtc* crtc) | ||||
| { | ||||
| 	 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| int hw_sm750_setColReg(struct lynxfb_crtc* crtc,ushort index, | ||||
| 								ushort red,ushort green,ushort blue) | ||||
| { | ||||
| 	static unsigned int add[]={PANEL_PALETTE_RAM,CRT_PALETTE_RAM}; | ||||
| 	POKE32(add[crtc->channel] + index*4 ,(red<<16)|(green<<8)|blue); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int hw_sm750le_setBLANK(struct lynxfb_output * output,int blank){ | ||||
| 	int dpms,crtdb; | ||||
| 	 | ||||
| 	switch(blank) | ||||
| 	{ | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_UNBLANK: | ||||
| #else | ||||
| 		case VESA_NO_BLANKING: | ||||
| #endif | ||||
| 			dpms = CRT_DISPLAY_CTRL_DPMS_0; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; | ||||
| 			break; | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_NORMAL: | ||||
| 			dpms = CRT_DISPLAY_CTRL_DPMS_0; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| #endif | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_VSYNC_SUSPEND: | ||||
| #else | ||||
| 		case VESA_VSYNC_SUSPEND: | ||||
| #endif | ||||
| 			dpms = CRT_DISPLAY_CTRL_DPMS_2; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_HSYNC_SUSPEND: | ||||
| #else | ||||
| 		case VESA_HSYNC_SUSPEND: | ||||
| #endif | ||||
| 			dpms = CRT_DISPLAY_CTRL_DPMS_1; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_POWERDOWN: | ||||
| #else | ||||
| 		case VESA_POWERDOWN: | ||||
| #endif | ||||
| 			dpms = CRT_DISPLAY_CTRL_DPMS_3; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	if(output->paths & sm750_crt){ | ||||
| 		POKE32(CRT_DISPLAY_CTRL,FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL),CRT_DISPLAY_CTRL,DPMS,dpms)); | ||||
| 		POKE32(CRT_DISPLAY_CTRL,FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL),CRT_DISPLAY_CTRL,BLANK,crtdb)); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int hw_sm750_setBLANK(struct lynxfb_output* output,int blank) | ||||
| { | ||||
| 	unsigned int dpms,pps,crtdb; | ||||
| 	 | ||||
| 	dpms = pps = crtdb = 0; | ||||
| 
 | ||||
| 	switch (blank) | ||||
| 	{ | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_UNBLANK: | ||||
| #else | ||||
| 		case VESA_NO_BLANKING: | ||||
| #endif | ||||
| 			pr_info("flag = FB_BLANK_UNBLANK \n"); | ||||
| 			dpms = SYSTEM_CTRL_DPMS_VPHP; | ||||
| 			pps = PANEL_DISPLAY_CTRL_DATA_ENABLE; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; | ||||
| 			break; | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_NORMAL: | ||||
| 			pr_info("flag = FB_BLANK_NORMAL \n"); | ||||
| 			dpms = SYSTEM_CTRL_DPMS_VPHP; | ||||
| 			pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| #endif | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_VSYNC_SUSPEND: | ||||
| #else | ||||
| 		case VESA_VSYNC_SUSPEND: | ||||
| #endif | ||||
| 			dpms = SYSTEM_CTRL_DPMS_VNHP; | ||||
| 			pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_HSYNC_SUSPEND: | ||||
| #else | ||||
| 		case VESA_HSYNC_SUSPEND: | ||||
| #endif | ||||
| 			dpms = SYSTEM_CTRL_DPMS_VPHN; | ||||
| 			pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) | ||||
| 		case FB_BLANK_POWERDOWN: | ||||
| #else | ||||
| 		case VESA_POWERDOWN: | ||||
| #endif | ||||
| 			dpms = SYSTEM_CTRL_DPMS_VNHN; | ||||
| 			pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; | ||||
| 			crtdb = CRT_DISPLAY_CTRL_BLANK_ON; | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	if(output->paths & sm750_crt){ | ||||
| 
 | ||||
| 		POKE32(SYSTEM_CTRL,FIELD_VALUE(PEEK32(SYSTEM_CTRL),SYSTEM_CTRL,DPMS,dpms)); | ||||
| 		POKE32(CRT_DISPLAY_CTRL,FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL),CRT_DISPLAY_CTRL,BLANK,crtdb)); | ||||
| 	} | ||||
| 
 | ||||
| 	if(output->paths & sm750_panel){ | ||||
| 		POKE32(PANEL_DISPLAY_CTRL,FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),PANEL_DISPLAY_CTRL,DATA,pps)); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void hw_sm750_initAccel(struct lynx_share * share) | ||||
| { | ||||
| 	u32 reg; | ||||
| 	enable2DEngine(1); | ||||
| 
 | ||||
| 	if(getChipType() == SM750LE){ | ||||
| 		reg = PEEK32(DE_STATE1); | ||||
| 		reg = FIELD_SET(reg,DE_STATE1,DE_ABORT,ON); | ||||
| 		POKE32(DE_STATE1,reg); | ||||
| 
 | ||||
| 		reg = PEEK32(DE_STATE1); | ||||
| 		reg = FIELD_SET(reg,DE_STATE1,DE_ABORT,OFF); | ||||
| 		POKE32(DE_STATE1,reg); | ||||
| 
 | ||||
| 	}else{ | ||||
| 		/* engine reset */ | ||||
| 		reg = PEEK32(SYSTEM_CTRL); | ||||
| 	    reg = FIELD_SET(reg,SYSTEM_CTRL,DE_ABORT,ON); | ||||
| 		POKE32(SYSTEM_CTRL,reg); | ||||
| 
 | ||||
| 		reg = PEEK32(SYSTEM_CTRL); | ||||
| 		reg = FIELD_SET(reg,SYSTEM_CTRL,DE_ABORT,OFF); | ||||
| 		POKE32(SYSTEM_CTRL,reg); | ||||
| 	} | ||||
| 
 | ||||
| 	/* call 2d init */ | ||||
| 	share->accel.de_init(&share->accel); | ||||
| } | ||||
| 
 | ||||
| int hw_sm750le_deWait() | ||||
| { | ||||
| 	int i=0x10000000; | ||||
| 	while(i--){ | ||||
| 		unsigned int dwVal = PEEK32(DE_STATE2); | ||||
| 		if((FIELD_GET(dwVal,DE_STATE2,DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && | ||||
| 			(FIELD_GET(dwVal,DE_STATE2,DE_FIFO)  == DE_STATE2_DE_FIFO_EMPTY) && | ||||
| 			(FIELD_GET(dwVal,DE_STATE2,DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) | ||||
| 		{ | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	/* timeout error */ | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int hw_sm750_deWait() | ||||
| { | ||||
| 	int i=0x10000000; | ||||
| 	while(i--){ | ||||
| 		unsigned int dwVal = PEEK32(SYSTEM_CTRL); | ||||
| 		if((FIELD_GET(dwVal,SYSTEM_CTRL,DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && | ||||
| 			(FIELD_GET(dwVal,SYSTEM_CTRL,DE_FIFO)  == SYSTEM_CTRL_DE_FIFO_EMPTY) && | ||||
| 			(FIELD_GET(dwVal,SYSTEM_CTRL,DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) | ||||
| 		{ | ||||
| 			return 0; | ||||
| 		} | ||||
| 	} | ||||
| 	/* timeout error */ | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| int hw_sm750_pan_display(struct lynxfb_crtc *crtc, | ||||
|         const struct fb_var_screeninfo *var, | ||||
|         const struct fb_info *info) | ||||
| { | ||||
|     uint32_t total; | ||||
|     //check params
 | ||||
|     if ((var->xoffset + var->xres > var->xres_virtual) || | ||||
|             (var->yoffset + var->yres > var->yres_virtual)) { | ||||
|         return -EINVAL; | ||||
|     } | ||||
| 
 | ||||
|     total = var->yoffset * info->fix.line_length + | ||||
|         ((var->xoffset * var->bits_per_pixel) >> 3); | ||||
|     total += crtc->oScreen; | ||||
|     if (crtc->channel == sm750_primary) { | ||||
|         POKE32(PANEL_FB_ADDRESS, | ||||
|                 FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS), | ||||
|                     PANEL_FB_ADDRESS, ADDRESS, total)); | ||||
|     } else { | ||||
|         POKE32(CRT_FB_ADDRESS, | ||||
|                 FIELD_VALUE(PEEK32(CRT_FB_ADDRESS), | ||||
|                     CRT_FB_ADDRESS, ADDRESS, total)); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										104
									
								
								drivers/staging/sm750fb/sm750_hw.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								drivers/staging/sm750fb/sm750_hw.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| #ifndef LYNX_HW750_H__ | ||||
| #define LYNX_HW750_H__ | ||||
| 
 | ||||
| 
 | ||||
| #define DEFAULT_SM750_CHIP_CLOCK 		290 | ||||
| #define DEFAULT_SM750LE_CHIP_CLOCK  	333 | ||||
| #ifndef SM750LE_REVISION_ID | ||||
| #define SM750LE_REVISION_ID (unsigned char)0xfe | ||||
| #endif | ||||
| 
 | ||||
| //#define DEFAULT_MEM_CLOCK	(DEFAULT_SM750_CHIP_CLOCK/1)
 | ||||
| //#define DEFAULT_MASTER_CLOCK	(DEFAULT_SM750_CHIP_CLOCK/3)
 | ||||
| 
 | ||||
| 
 | ||||
| enum sm750_pnltype{ | ||||
| 
 | ||||
| 	sm750_24TFT = 0,/* 24bit tft */ | ||||
| 
 | ||||
| 	sm750_dualTFT = 2,/* dual 18 bit tft */ | ||||
| 
 | ||||
| 	sm750_doubleTFT = 1,/* 36 bit double pixel tft */ | ||||
| }; | ||||
| 
 | ||||
| /* vga channel is not concerned  */ | ||||
| enum sm750_dataflow{ | ||||
| 	sm750_simul_pri,/* primary => all head */ | ||||
| 
 | ||||
| 	sm750_simul_sec,/* secondary => all head */ | ||||
| 
 | ||||
| 	sm750_dual_normal,/* 	primary => panel head and secondary => crt */ | ||||
| 
 | ||||
| 	sm750_dual_swap,/* 	primary => crt head and secondary => panel */ | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| enum sm750_channel{ | ||||
| 	sm750_primary = 0, | ||||
| 	/* enum value equal to the register filed data */ | ||||
| 	sm750_secondary = 1, | ||||
| }; | ||||
| 
 | ||||
| enum sm750_path{ | ||||
| 	sm750_panel = 1, | ||||
| 	sm750_crt = 2, | ||||
| 	sm750_pnc = 3,/* panel and crt */ | ||||
| }; | ||||
| 
 | ||||
| struct init_status{ | ||||
| 	ushort powerMode; | ||||
| 	/* below three clocks are in unit of MHZ*/ | ||||
| 	ushort chip_clk; | ||||
| 	ushort mem_clk; | ||||
| 	ushort master_clk; | ||||
| 	ushort setAllEngOff; | ||||
| 	ushort resetMemory; | ||||
| }; | ||||
| 
 | ||||
| struct sm750_state{ | ||||
| 	struct init_status initParm; | ||||
| 	enum sm750_pnltype pnltype; | ||||
| 	enum sm750_dataflow dataflow; | ||||
| 	int nocrt; | ||||
| 	int xLCD; | ||||
| 	int yLCD; | ||||
| }; | ||||
| 
 | ||||
| /* 	sm750_share stands for a presentation of two frame buffer
 | ||||
| 	that use one sm750 adaptor, it is similiar to the super class of lynx_share | ||||
| 	in C++ | ||||
| */ | ||||
| 
 | ||||
| struct sm750_share{ | ||||
| 	/* it's better to put lynx_share struct to the first place of sm750_share */ | ||||
| 	struct lynx_share share; | ||||
| 	struct sm750_state state; | ||||
| 	int hwCursor; | ||||
| 	/* 	0: no hardware cursor
 | ||||
| 		1: primary crtc hw cursor enabled, | ||||
| 		2: secondary crtc hw cursor enabled | ||||
| 		3: both ctrc hw cursor enabled | ||||
| 	*/ | ||||
| }; | ||||
| 
 | ||||
| int hw_sm750_map(struct lynx_share* share,struct pci_dev* pdev); | ||||
| int hw_sm750_inithw(struct lynx_share*,struct pci_dev *); | ||||
| void hw_sm750_initAccel(struct lynx_share *); | ||||
| int hw_sm750_deWait(void); | ||||
| int hw_sm750le_deWait(void); | ||||
| 
 | ||||
| resource_size_t hw_sm750_getVMSize(struct lynx_share *); | ||||
| int hw_sm750_output_checkMode(struct lynxfb_output*,struct fb_var_screeninfo*); | ||||
| int hw_sm750_output_setMode(struct lynxfb_output*,struct fb_var_screeninfo*,struct fb_fix_screeninfo*); | ||||
| int hw_sm750_crtc_checkMode(struct lynxfb_crtc*,struct fb_var_screeninfo*); | ||||
| int hw_sm750_crtc_setMode(struct lynxfb_crtc*,struct fb_var_screeninfo*,struct fb_fix_screeninfo*); | ||||
| int hw_sm750_setColReg(struct lynxfb_crtc*,ushort,ushort,ushort,ushort); | ||||
| int hw_sm750_setBLANK(struct lynxfb_output*,int); | ||||
| int hw_sm750le_setBLANK(struct lynxfb_output*,int); | ||||
| void hw_sm750_crtc_clear(struct lynxfb_crtc*); | ||||
| void hw_sm750_output_clear(struct lynxfb_output*); | ||||
| int hw_sm750_pan_display(struct lynxfb_crtc *crtc, | ||||
|         const struct fb_var_screeninfo *var, | ||||
|         const struct fb_info *info); | ||||
| 
 | ||||
| #endif | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user