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