root/drivers/staging/sm750fb/ddk750_display.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_display_control
  2. primary_wait_vertical_sync
  3. sw_panel_power_sequence
  4. ddk750_set_logical_disp_out

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include "ddk750_reg.h"
   3 #include "ddk750_chip.h"
   4 #include "ddk750_display.h"
   5 #include "ddk750_power.h"
   6 #include "ddk750_dvi.h"
   7 
   8 static void set_display_control(int ctrl, int disp_state)
   9 {
  10         /* state != 0 means turn on both timing & plane en_bit */
  11         unsigned long reg, val, reserved;
  12         int cnt = 0;
  13 
  14         if (!ctrl) {
  15                 reg = PANEL_DISPLAY_CTRL;
  16                 reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK;
  17         } else {
  18                 reg = CRT_DISPLAY_CTRL;
  19                 reserved = CRT_DISPLAY_CTRL_RESERVED_MASK;
  20         }
  21 
  22         val = peek32(reg);
  23         if (disp_state) {
  24                 /*
  25                  * Timing should be enabled first before enabling the
  26                  * plane because changing at the same time does not
  27                  * guarantee that the plane will also enabled or
  28                  * disabled.
  29                  */
  30                 val |= DISPLAY_CTRL_TIMING;
  31                 poke32(reg, val);
  32 
  33                 val |= DISPLAY_CTRL_PLANE;
  34 
  35                 /*
  36                  * Somehow the register value on the plane is not set
  37                  * until a few delay. Need to write and read it a
  38                  * couple times
  39                  */
  40                 do {
  41                         cnt++;
  42                         poke32(reg, val);
  43                 } while ((peek32(reg) & ~reserved) != (val & ~reserved));
  44                 pr_debug("Set Plane enbit:after tried %d times\n", cnt);
  45         } else {
  46                 /*
  47                  * When turning off, there is no rule on the
  48                  * programming sequence since whenever the clock is
  49                  * off, then it does not matter whether the plane is
  50                  * enabled or disabled.  Note: Modifying the plane bit
  51                  * will take effect on the next vertical sync. Need to
  52                  * find out if it is necessary to wait for 1 vsync
  53                  * before modifying the timing enable bit.
  54                  */
  55                 val &= ~DISPLAY_CTRL_PLANE;
  56                 poke32(reg, val);
  57 
  58                 val &= ~DISPLAY_CTRL_TIMING;
  59                 poke32(reg, val);
  60         }
  61 }
  62 
  63 static void primary_wait_vertical_sync(int delay)
  64 {
  65         unsigned int status;
  66 
  67         /*
  68          * Do not wait when the Primary PLL is off or display control is
  69          * already off. This will prevent the software to wait forever.
  70          */
  71         if (!(peek32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) ||
  72             !(peek32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING))
  73                 return;
  74 
  75         while (delay-- > 0) {
  76                 /* Wait for end of vsync. */
  77                 do {
  78                         status = peek32(SYSTEM_CTRL);
  79                 } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE);
  80 
  81                 /* Wait for start of vsync. */
  82                 do {
  83                         status = peek32(SYSTEM_CTRL);
  84                 } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE));
  85         }
  86 }
  87 
  88 static void sw_panel_power_sequence(int disp, int delay)
  89 {
  90         unsigned int reg;
  91 
  92         /* disp should be 1 to open sequence */
  93         reg = peek32(PANEL_DISPLAY_CTRL);
  94         reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
  95         poke32(PANEL_DISPLAY_CTRL, reg);
  96         primary_wait_vertical_sync(delay);
  97 
  98         reg = peek32(PANEL_DISPLAY_CTRL);
  99         reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0);
 100         poke32(PANEL_DISPLAY_CTRL, reg);
 101         primary_wait_vertical_sync(delay);
 102 
 103         reg = peek32(PANEL_DISPLAY_CTRL);
 104         reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0);
 105         poke32(PANEL_DISPLAY_CTRL, reg);
 106         primary_wait_vertical_sync(delay);
 107 
 108         reg = peek32(PANEL_DISPLAY_CTRL);
 109         reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0);
 110         poke32(PANEL_DISPLAY_CTRL, reg);
 111         primary_wait_vertical_sync(delay);
 112 }
 113 
 114 void ddk750_set_logical_disp_out(enum disp_output output)
 115 {
 116         unsigned int reg;
 117 
 118         if (output & PNL_2_USAGE) {
 119                 /* set panel path controller select */
 120                 reg = peek32(PANEL_DISPLAY_CTRL);
 121                 reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK;
 122                 reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) <<
 123                         PANEL_DISPLAY_CTRL_SELECT_SHIFT);
 124                 poke32(PANEL_DISPLAY_CTRL, reg);
 125         }
 126 
 127         if (output & CRT_2_USAGE) {
 128                 /* set crt path controller select */
 129                 reg = peek32(CRT_DISPLAY_CTRL);
 130                 reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK;
 131                 reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) <<
 132                         CRT_DISPLAY_CTRL_SELECT_SHIFT);
 133                 /*se blank off */
 134                 reg &= ~CRT_DISPLAY_CTRL_BLANK;
 135                 poke32(CRT_DISPLAY_CTRL, reg);
 136         }
 137 
 138         if (output & PRI_TP_USAGE) {
 139                 /* set primary timing and plane en_bit */
 140                 set_display_control(0, (output & PRI_TP_MASK) >> PRI_TP_OFFSET);
 141         }
 142 
 143         if (output & SEC_TP_USAGE) {
 144                 /* set secondary timing and plane en_bit*/
 145                 set_display_control(1, (output & SEC_TP_MASK) >> SEC_TP_OFFSET);
 146         }
 147 
 148         if (output & PNL_SEQ_USAGE) {
 149                 /* set  panel sequence */
 150                 sw_panel_power_sequence((output & PNL_SEQ_MASK) >> PNL_SEQ_OFFSET,
 151                 4);
 152         }
 153 
 154         if (output & DAC_USAGE)
 155                 set_DAC((output & DAC_MASK) >> DAC_OFFSET);
 156 
 157         if (output & DPMS_USAGE)
 158                 ddk750_set_dpms((output & DPMS_MASK) >> DPMS_OFFSET);
 159 }

/* [<][>][^][v][top][bottom][index][help] */