summaryrefslogblamecommitdiffstats
path: root/drivers/staging/sm750fb/ddk750_display.c
blob: ca4973ee49e4204780026434071c4220b1d2af6d (plain) (tree)
1
2
3
4
5
6
7
8
9





                           
                                                                     
 
                                                       

                                                                 

                                         
 
                    

                                                            
                


                                                          
 







                                                                     
                                           

                                 
                                          




















                                                                         
                                           

                                 
                                            
                                 


         
                                                     

                            
 
                    

                                        

                                                                                             
                                                                 
                                                                          


                               
                                     
                                                    
                            

                                                                          

                                                      
                            

                                                                             
                 
 
                


                                                                                             
                                                               
                                                                        


                               
                                     
                                                    
                            

                                                                          

                                                      
                            

                                                                             



                 
                                                     




                                               
                                                    
                                        

                                       
                                         
                                                    
                                        


                                         
                                                       
                                        

                                       
                                         
                                                    
                                        






                                                   
 
                                   

                                                      


                                                                  
                                                

         
                                   

                                                    


                                                                  
                                 
                                               
                                              


         
                                    
                                                         
                                                                              

         
                                    
                                                          
                                                                              

         
                                     
                                         
                                                                                   

         
                               
                                                          
 
                                

                                                                    
#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 disp_state)
{
	/* state != 0 means turn on both timing & plane en_bit */
	unsigned long reg, val, reserved;
	int cnt = 0;

	if (!ctrl) {
		reg = PANEL_DISPLAY_CTRL;
		reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK;
	} else {
		reg = CRT_DISPLAY_CTRL;
		reserved = CRT_DISPLAY_CTRL_RESERVED_MASK;
	}

	val = PEEK32(reg);
	if (disp_state) {
		/*
		 * 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.
		 */
		val |= DISPLAY_CTRL_TIMING;
		POKE32(reg, val);

		val |= DISPLAY_CTRL_PLANE;

		/*
		 * 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(reg, val);
		} while ((PEEK32(reg) & ~reserved) != (val & ~reserved));
		pr_debug("Set 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.
		 */
		val &= ~DISPLAY_CTRL_PLANE;
		POKE32(reg, val);

		val &= ~DISPLAY_CTRL_TIMING;
		POKE32(reg, val);
	}
}

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 (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) ||
		    !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) {
			return;
		}

		while (delay-- > 0) {
			/* Wait for end of vsync. */
			do {
				status = PEEK32(SYSTEM_CTRL);
			} while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);

			/* Wait for start of vsync. */
			do {
				status = PEEK32(SYSTEM_CTRL);
			} while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
		}

	} 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 (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) ||
		    !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) {
			return;
		}

		while (delay-- > 0) {
			/* Wait for end of vsync. */
			do {
				status = PEEK32(SYSTEM_CTRL);
			} while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);

			/* Wait for start of vsync. */
			do {
				status = PEEK32(SYSTEM_CTRL);
			} while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
		}
	}
}

static void swPanelPowerSequence(int disp, int delay)
{
	unsigned int reg;

	/* disp should be 1 to open sequence */
	reg = PEEK32(PANEL_DISPLAY_CTRL);
	reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
	POKE32(PANEL_DISPLAY_CTRL, reg);
	primaryWaitVerticalSync(delay);

	reg = PEEK32(PANEL_DISPLAY_CTRL);
	reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0);
	POKE32(PANEL_DISPLAY_CTRL, reg);
	primaryWaitVerticalSync(delay);

	reg = PEEK32(PANEL_DISPLAY_CTRL);
	reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0);
	POKE32(PANEL_DISPLAY_CTRL, reg);
	primaryWaitVerticalSync(delay);

	reg = PEEK32(PANEL_DISPLAY_CTRL);
	reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
	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 &= ~PANEL_DISPLAY_CTRL_SELECT_MASK;
		reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) <<
			PANEL_DISPLAY_CTRL_SELECT_SHIFT);
		POKE32(PANEL_DISPLAY_CTRL, reg);
	}

	if (output & CRT_2_USAGE) {
		/* set crt path controller select */
		reg = PEEK32(CRT_DISPLAY_CTRL);
		reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK;
		reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) <<
			CRT_DISPLAY_CTRL_SELECT_SHIFT);
		/*se blank off */
		reg &= ~CRT_DISPLAY_CTRL_BLANK;
		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);
}