diff options
Diffstat (limited to 'drivers/gpu/drm/i915/dvo_ns2501.c')
| -rw-r--r-- | drivers/gpu/drm/i915/dvo_ns2501.c | 670 |
1 files changed, 374 insertions, 296 deletions
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c index 441630434d34..97ae8aa157e9 100644 --- a/drivers/gpu/drm/i915/dvo_ns2501.c +++ b/drivers/gpu/drm/i915/dvo_ns2501.c | |||
| @@ -60,6 +60,130 @@ | |||
| 60 | 60 | ||
| 61 | #define NS2501_REGC 0x0c | 61 | #define NS2501_REGC 0x0c |
| 62 | 62 | ||
| 63 | /* | ||
| 64 | * The following registers are not part of the official datasheet | ||
| 65 | * and are the result of reverse engineering. | ||
| 66 | */ | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Register c0 controls how the DVO synchronizes with | ||
| 70 | * its input. | ||
| 71 | */ | ||
| 72 | #define NS2501_REGC0 0xc0 | ||
| 73 | #define NS2501_C0_ENABLE (1<<0) /* enable the DVO sync in general */ | ||
| 74 | #define NS2501_C0_HSYNC (1<<1) /* synchronize horizontal with input */ | ||
| 75 | #define NS2501_C0_VSYNC (1<<2) /* synchronize vertical with input */ | ||
| 76 | #define NS2501_C0_RESET (1<<7) /* reset the synchronization flip/flops */ | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Register 41 is somehow related to the sync register and sync | ||
| 80 | * configuration. It should be 0x32 whenever regC0 is 0x05 (hsync off) | ||
| 81 | * and 0x00 otherwise. | ||
| 82 | */ | ||
| 83 | #define NS2501_REG41 0x41 | ||
| 84 | |||
| 85 | /* | ||
| 86 | * this register controls the dithering of the DVO | ||
| 87 | * One bit enables it, the other define the dithering depth. | ||
| 88 | * The higher the value, the lower the dithering depth. | ||
| 89 | */ | ||
| 90 | #define NS2501_F9_REG 0xf9 | ||
| 91 | #define NS2501_F9_ENABLE (1<<0) /* if set, dithering is enabled */ | ||
| 92 | #define NS2501_F9_DITHER_MASK (0x7f<<1) /* controls the dither depth */ | ||
| 93 | #define NS2501_F9_DITHER_SHIFT 1 /* shifts the dither mask */ | ||
| 94 | |||
| 95 | /* | ||
| 96 | * PLL configuration register. This is a pair of registers, | ||
| 97 | * one single byte register at 1B, and a pair at 1C,1D. | ||
| 98 | * These registers are counters/dividers. | ||
| 99 | */ | ||
| 100 | #define NS2501_REG1B 0x1b /* one byte PLL control register */ | ||
| 101 | #define NS2501_REG1C 0x1c /* low-part of the second register */ | ||
| 102 | #define NS2501_REG1D 0x1d /* high-part of the second register */ | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Scaler control registers. Horizontal at b8,b9, | ||
| 106 | * vertical at 10,11. The scale factor is computed as | ||
| 107 | * 2^16/control-value. The low-byte comes first. | ||
| 108 | */ | ||
| 109 | #define NS2501_REG10 0x10 /* low-byte vertical scaler */ | ||
| 110 | #define NS2501_REG11 0x11 /* high-byte vertical scaler */ | ||
| 111 | #define NS2501_REGB8 0xb8 /* low-byte horizontal scaler */ | ||
| 112 | #define NS2501_REGB9 0xb9 /* high-byte horizontal scaler */ | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Display window definition. This consists of four registers | ||
| 116 | * per dimension. One register pair defines the start of the | ||
| 117 | * display, one the end. | ||
| 118 | * As far as I understand, this defines the window within which | ||
| 119 | * the scaler samples the input. | ||
| 120 | */ | ||
| 121 | #define NS2501_REGC1 0xc1 /* low-byte horizontal display start */ | ||
| 122 | #define NS2501_REGC2 0xc2 /* high-byte horizontal display start */ | ||
| 123 | #define NS2501_REGC3 0xc3 /* low-byte horizontal display stop */ | ||
| 124 | #define NS2501_REGC4 0xc4 /* high-byte horizontal display stop */ | ||
| 125 | #define NS2501_REGC5 0xc5 /* low-byte vertical display start */ | ||
| 126 | #define NS2501_REGC6 0xc6 /* high-byte vertical display start */ | ||
| 127 | #define NS2501_REGC7 0xc7 /* low-byte vertical display stop */ | ||
| 128 | #define NS2501_REGC8 0xc8 /* high-byte vertical display stop */ | ||
| 129 | |||
| 130 | /* | ||
| 131 | * The following register pair seems to define the start of | ||
| 132 | * the vertical sync. If automatic syncing is enabled, and the | ||
| 133 | * register value defines a sync pulse that is later than the | ||
| 134 | * incoming sync, then the register value is ignored and the | ||
| 135 | * external hsync triggers the synchronization. | ||
| 136 | */ | ||
| 137 | #define NS2501_REG80 0x80 /* low-byte vsync-start */ | ||
| 138 | #define NS2501_REG81 0x81 /* high-byte vsync-start */ | ||
| 139 | |||
| 140 | /* | ||
| 141 | * The following register pair seems to define the total number | ||
| 142 | * of lines created at the output side of the scaler. | ||
| 143 | * This is again a low-high register pair. | ||
| 144 | */ | ||
| 145 | #define NS2501_REG82 0x82 /* output display height, low byte */ | ||
| 146 | #define NS2501_REG83 0x83 /* output display height, high byte */ | ||
| 147 | |||
| 148 | /* | ||
| 149 | * The following registers define the end of the front-porch | ||
| 150 | * in horizontal and vertical position and hence allow to shift | ||
| 151 | * the image left/right or up/down. | ||
| 152 | */ | ||
| 153 | #define NS2501_REG98 0x98 /* horizontal start of display + 256, low */ | ||
| 154 | #define NS2501_REG99 0x99 /* horizontal start of display + 256, high */ | ||
| 155 | #define NS2501_REG8E 0x8e /* vertical start of the display, low byte */ | ||
| 156 | #define NS2501_REG8F 0x8f /* vertical start of the display, high byte */ | ||
| 157 | |||
| 158 | /* | ||
| 159 | * The following register pair control the function of the | ||
| 160 | * backlight and the DVO output. To enable the corresponding | ||
| 161 | * function, the corresponding bit must be set in both registers. | ||
| 162 | */ | ||
| 163 | #define NS2501_REG34 0x34 /* DVO enable functions, first register */ | ||
| 164 | #define NS2501_REG35 0x35 /* DVO enable functions, second register */ | ||
| 165 | #define NS2501_34_ENABLE_OUTPUT (1<<0) /* enable DVO output */ | ||
| 166 | #define NS2501_34_ENABLE_BACKLIGHT (1<<1) /* enable backlight */ | ||
| 167 | |||
| 168 | /* | ||
| 169 | * Registers 9C and 9D define the vertical output offset | ||
| 170 | * of the visible region. | ||
| 171 | */ | ||
| 172 | #define NS2501_REG9C 0x9c | ||
| 173 | #define NS2501_REG9D 0x9d | ||
| 174 | |||
| 175 | /* | ||
| 176 | * The register 9F defines the dithering. This requires the | ||
| 177 | * scaler to be ON. Bit 0 enables dithering, the remaining | ||
| 178 | * bits control the depth of the dither. The higher the value, | ||
| 179 | * the LOWER the dithering amplitude. A good value seems to be | ||
| 180 | * 15 (total register value). | ||
| 181 | */ | ||
| 182 | #define NS2501_REGF9 0xf9 | ||
| 183 | #define NS2501_F9_ENABLE_DITHER (1<<0) /* enable dithering */ | ||
| 184 | #define NS2501_F9_DITHER_MASK (0x7f<<1) /* dither masking */ | ||
| 185 | #define NS2501_F9_DITHER_SHIFT 1 /* upshift of the dither mask */ | ||
| 186 | |||
| 63 | enum { | 187 | enum { |
| 64 | MODE_640x480, | 188 | MODE_640x480, |
| 65 | MODE_800x600, | 189 | MODE_800x600, |
| @@ -72,274 +196,178 @@ struct ns2501_reg { | |||
| 72 | }; | 196 | }; |
| 73 | 197 | ||
| 74 | /* | 198 | /* |
| 75 | * Magic values based on what the BIOS on | 199 | * The following structure keeps the complete configuration of |
| 76 | * Fujitsu-Siemens Lifebook S6010 programs (1024x768 panel). | 200 | * the DVO, given a specific output configuration. |
| 201 | * This is pretty much guess-work from reverse-engineering, so | ||
| 202 | * read all this with a grain of salt. | ||
| 203 | */ | ||
| 204 | struct ns2501_configuration { | ||
| 205 | uint8_t sync; /* configuration of the C0 register */ | ||
| 206 | uint8_t conf; /* configuration register 8 */ | ||
| 207 | uint8_t syncb; /* configuration register 41 */ | ||
| 208 | uint8_t dither; /* configuration of the dithering */ | ||
| 209 | uint8_t pll_a; /* PLL configuration, register A, 1B */ | ||
| 210 | uint16_t pll_b; /* PLL configuration, register B, 1C/1D */ | ||
| 211 | uint16_t hstart; /* horizontal start, registers C1/C2 */ | ||
| 212 | uint16_t hstop; /* horizontal total, registers C3/C4 */ | ||
| 213 | uint16_t vstart; /* vertical start, registers C5/C6 */ | ||
| 214 | uint16_t vstop; /* vertical total, registers C7/C8 */ | ||
| 215 | uint16_t vsync; /* manual vertical sync start, 80/81 */ | ||
| 216 | uint16_t vtotal; /* number of lines generated, 82/83 */ | ||
| 217 | uint16_t hpos; /* horizontal position + 256, 98/99 */ | ||
| 218 | uint16_t vpos; /* vertical position, 8e/8f */ | ||
| 219 | uint16_t voffs; /* vertical output offset, 9c/9d */ | ||
| 220 | uint16_t hscale; /* horizontal scaling factor, b8/b9 */ | ||
| 221 | uint16_t vscale; /* vertical scaling factor, 10/11 */ | ||
| 222 | }; | ||
| 223 | |||
| 224 | /* | ||
| 225 | * DVO configuration values, partially based on what the BIOS | ||
| 226 | * of the Fujitsu Lifebook S6010 writes into registers, | ||
| 227 | * partially found by manual tweaking. These configurations assume | ||
| 228 | * a 1024x768 panel. | ||
| 77 | */ | 229 | */ |
| 78 | static const struct ns2501_reg regs_1024x768[][86] = { | 230 | static const struct ns2501_configuration ns2501_modes[] = { |
| 79 | [MODE_640x480] = { | 231 | [MODE_640x480] = { |
| 80 | [0] = { .offset = 0x0a, .value = 0x81, }, | 232 | .sync = NS2501_C0_ENABLE | NS2501_C0_VSYNC, |
| 81 | [1] = { .offset = 0x18, .value = 0x07, }, | 233 | .conf = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD, |
| 82 | [2] = { .offset = 0x19, .value = 0x00, }, | 234 | .syncb = 0x32, |
| 83 | [3] = { .offset = 0x1a, .value = 0x00, }, | 235 | .dither = 0x0f, |
| 84 | [4] = { .offset = 0x1b, .value = 0x11, }, | 236 | .pll_a = 17, |
| 85 | [5] = { .offset = 0x1c, .value = 0x54, }, | 237 | .pll_b = 852, |
| 86 | [6] = { .offset = 0x1d, .value = 0x03, }, | 238 | .hstart = 144, |
| 87 | [7] = { .offset = 0x1e, .value = 0x02, }, | 239 | .hstop = 783, |
| 88 | [8] = { .offset = 0xf3, .value = 0x90, }, | 240 | .vstart = 22, |
| 89 | [9] = { .offset = 0xf9, .value = 0x00, }, | 241 | .vstop = 514, |
| 90 | [10] = { .offset = 0xc1, .value = 0x90, }, | 242 | .vsync = 2047, /* actually, ignored with this config */ |
| 91 | [11] = { .offset = 0xc2, .value = 0x00, }, | 243 | .vtotal = 1341, |
| 92 | [12] = { .offset = 0xc3, .value = 0x0f, }, | 244 | .hpos = 0, |
| 93 | [13] = { .offset = 0xc4, .value = 0x03, }, | 245 | .vpos = 16, |
| 94 | [14] = { .offset = 0xc5, .value = 0x16, }, | 246 | .voffs = 36, |
| 95 | [15] = { .offset = 0xc6, .value = 0x00, }, | 247 | .hscale = 40960, |
| 96 | [16] = { .offset = 0xc7, .value = 0x02, }, | 248 | .vscale = 40960 |
| 97 | [17] = { .offset = 0xc8, .value = 0x02, }, | ||
| 98 | [18] = { .offset = 0xf4, .value = 0x00, }, | ||
| 99 | [19] = { .offset = 0x80, .value = 0xff, }, | ||
| 100 | [20] = { .offset = 0x81, .value = 0x07, }, | ||
| 101 | [21] = { .offset = 0x82, .value = 0x3d, }, | ||
| 102 | [22] = { .offset = 0x83, .value = 0x05, }, | ||
| 103 | [23] = { .offset = 0x94, .value = 0x00, }, | ||
| 104 | [24] = { .offset = 0x95, .value = 0x00, }, | ||
| 105 | [25] = { .offset = 0x96, .value = 0x05, }, | ||
| 106 | [26] = { .offset = 0x97, .value = 0x00, }, | ||
| 107 | [27] = { .offset = 0x9a, .value = 0x88, }, | ||
| 108 | [28] = { .offset = 0x9b, .value = 0x00, }, | ||
| 109 | [29] = { .offset = 0x98, .value = 0x00, }, | ||
| 110 | [30] = { .offset = 0x99, .value = 0x00, }, | ||
| 111 | [31] = { .offset = 0xf7, .value = 0x88, }, | ||
| 112 | [32] = { .offset = 0xf8, .value = 0x0a, }, | ||
| 113 | [33] = { .offset = 0x9c, .value = 0x24, }, | ||
| 114 | [34] = { .offset = 0x9d, .value = 0x00, }, | ||
| 115 | [35] = { .offset = 0x9e, .value = 0x25, }, | ||
| 116 | [36] = { .offset = 0x9f, .value = 0x03, }, | ||
| 117 | [37] = { .offset = 0xa0, .value = 0x28, }, | ||
| 118 | [38] = { .offset = 0xa1, .value = 0x01, }, | ||
| 119 | [39] = { .offset = 0xa2, .value = 0x28, }, | ||
| 120 | [40] = { .offset = 0xa3, .value = 0x05, }, | ||
| 121 | [41] = { .offset = 0xb6, .value = 0x09, }, | ||
| 122 | [42] = { .offset = 0xb8, .value = 0x00, }, | ||
| 123 | [43] = { .offset = 0xb9, .value = 0xa0, }, | ||
| 124 | [44] = { .offset = 0xba, .value = 0x00, }, | ||
| 125 | [45] = { .offset = 0xbb, .value = 0x20, }, | ||
| 126 | [46] = { .offset = 0x10, .value = 0x00, }, | ||
| 127 | [47] = { .offset = 0x11, .value = 0xa0, }, | ||
| 128 | [48] = { .offset = 0x12, .value = 0x02, }, | ||
| 129 | [49] = { .offset = 0x20, .value = 0x00, }, | ||
| 130 | [50] = { .offset = 0x22, .value = 0x00, }, | ||
| 131 | [51] = { .offset = 0x23, .value = 0x00, }, | ||
| 132 | [52] = { .offset = 0x24, .value = 0x00, }, | ||
| 133 | [53] = { .offset = 0x25, .value = 0x00, }, | ||
| 134 | [54] = { .offset = 0x8c, .value = 0x10, }, | ||
| 135 | [55] = { .offset = 0x8d, .value = 0x02, }, | ||
| 136 | [56] = { .offset = 0x8e, .value = 0x10, }, | ||
| 137 | [57] = { .offset = 0x8f, .value = 0x00, }, | ||
| 138 | [58] = { .offset = 0x90, .value = 0xff, }, | ||
| 139 | [59] = { .offset = 0x91, .value = 0x07, }, | ||
| 140 | [60] = { .offset = 0x92, .value = 0xa0, }, | ||
| 141 | [61] = { .offset = 0x93, .value = 0x02, }, | ||
| 142 | [62] = { .offset = 0xa5, .value = 0x00, }, | ||
| 143 | [63] = { .offset = 0xa6, .value = 0x00, }, | ||
| 144 | [64] = { .offset = 0xa7, .value = 0x00, }, | ||
| 145 | [65] = { .offset = 0xa8, .value = 0x00, }, | ||
| 146 | [66] = { .offset = 0xa9, .value = 0x04, }, | ||
| 147 | [67] = { .offset = 0xaa, .value = 0x70, }, | ||
| 148 | [68] = { .offset = 0xab, .value = 0x4f, }, | ||
| 149 | [69] = { .offset = 0xac, .value = 0x00, }, | ||
| 150 | [70] = { .offset = 0xa4, .value = 0x84, }, | ||
| 151 | [71] = { .offset = 0x7e, .value = 0x18, }, | ||
| 152 | [72] = { .offset = 0x84, .value = 0x00, }, | ||
| 153 | [73] = { .offset = 0x85, .value = 0x00, }, | ||
| 154 | [74] = { .offset = 0x86, .value = 0x00, }, | ||
| 155 | [75] = { .offset = 0x87, .value = 0x00, }, | ||
| 156 | [76] = { .offset = 0x88, .value = 0x00, }, | ||
| 157 | [77] = { .offset = 0x89, .value = 0x00, }, | ||
| 158 | [78] = { .offset = 0x8a, .value = 0x00, }, | ||
| 159 | [79] = { .offset = 0x8b, .value = 0x00, }, | ||
| 160 | [80] = { .offset = 0x26, .value = 0x00, }, | ||
| 161 | [81] = { .offset = 0x27, .value = 0x00, }, | ||
| 162 | [82] = { .offset = 0xad, .value = 0x00, }, | ||
| 163 | [83] = { .offset = 0x08, .value = 0x30, }, /* 0x31 */ | ||
| 164 | [84] = { .offset = 0x41, .value = 0x00, }, | ||
| 165 | [85] = { .offset = 0xc0, .value = 0x05, }, | ||
| 166 | }, | 249 | }, |
| 167 | [MODE_800x600] = { | 250 | [MODE_800x600] = { |
| 168 | [0] = { .offset = 0x0a, .value = 0x81, }, | 251 | .sync = NS2501_C0_ENABLE | |
| 169 | [1] = { .offset = 0x18, .value = 0x07, }, | 252 | NS2501_C0_HSYNC | NS2501_C0_VSYNC, |
| 170 | [2] = { .offset = 0x19, .value = 0x00, }, | 253 | .conf = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD, |
| 171 | [3] = { .offset = 0x1a, .value = 0x00, }, | 254 | .syncb = 0x00, |
| 172 | [4] = { .offset = 0x1b, .value = 0x19, }, | 255 | .dither = 0x0f, |
| 173 | [5] = { .offset = 0x1c, .value = 0x64, }, | 256 | .pll_a = 25, |
| 174 | [6] = { .offset = 0x1d, .value = 0x02, }, | 257 | .pll_b = 612, |
| 175 | [7] = { .offset = 0x1e, .value = 0x02, }, | 258 | .hstart = 215, |
| 176 | [8] = { .offset = 0xf3, .value = 0x90, }, | 259 | .hstop = 1016, |
| 177 | [9] = { .offset = 0xf9, .value = 0x00, }, | 260 | .vstart = 26, |
| 178 | [10] = { .offset = 0xc1, .value = 0xd7, }, | 261 | .vstop = 627, |
| 179 | [11] = { .offset = 0xc2, .value = 0x00, }, | 262 | .vsync = 807, |
| 180 | [12] = { .offset = 0xc3, .value = 0xf8, }, | 263 | .vtotal = 1341, |
| 181 | [13] = { .offset = 0xc4, .value = 0x03, }, | 264 | .hpos = 0, |
| 182 | [14] = { .offset = 0xc5, .value = 0x1a, }, | 265 | .vpos = 4, |
| 183 | [15] = { .offset = 0xc6, .value = 0x00, }, | 266 | .voffs = 35, |
| 184 | [16] = { .offset = 0xc7, .value = 0x73, }, | 267 | .hscale = 51248, |
| 185 | [17] = { .offset = 0xc8, .value = 0x02, }, | 268 | .vscale = 51232 |
| 186 | [18] = { .offset = 0xf4, .value = 0x00, }, | ||
| 187 | [19] = { .offset = 0x80, .value = 0x27, }, | ||
| 188 | [20] = { .offset = 0x81, .value = 0x03, }, | ||
| 189 | [21] = { .offset = 0x82, .value = 0x41, }, | ||
| 190 | [22] = { .offset = 0x83, .value = 0x05, }, | ||
| 191 | [23] = { .offset = 0x94, .value = 0x00, }, | ||
| 192 | [24] = { .offset = 0x95, .value = 0x00, }, | ||
| 193 | [25] = { .offset = 0x96, .value = 0x05, }, | ||
| 194 | [26] = { .offset = 0x97, .value = 0x00, }, | ||
| 195 | [27] = { .offset = 0x9a, .value = 0x88, }, | ||
| 196 | [28] = { .offset = 0x9b, .value = 0x00, }, | ||
| 197 | [29] = { .offset = 0x98, .value = 0x00, }, | ||
| 198 | [30] = { .offset = 0x99, .value = 0x00, }, | ||
| 199 | [31] = { .offset = 0xf7, .value = 0x88, }, | ||
| 200 | [32] = { .offset = 0xf8, .value = 0x06, }, | ||
| 201 | [33] = { .offset = 0x9c, .value = 0x23, }, | ||
| 202 | [34] = { .offset = 0x9d, .value = 0x00, }, | ||
| 203 | [35] = { .offset = 0x9e, .value = 0x25, }, | ||
| 204 | [36] = { .offset = 0x9f, .value = 0x03, }, | ||
| 205 | [37] = { .offset = 0xa0, .value = 0x28, }, | ||
| 206 | [38] = { .offset = 0xa1, .value = 0x01, }, | ||
| 207 | [39] = { .offset = 0xa2, .value = 0x28, }, | ||
| 208 | [40] = { .offset = 0xa3, .value = 0x05, }, | ||
| 209 | [41] = { .offset = 0xb6, .value = 0x09, }, | ||
| 210 | [42] = { .offset = 0xb8, .value = 0x30, }, | ||
| 211 | [43] = { .offset = 0xb9, .value = 0xc8, }, | ||
| 212 | [44] = { .offset = 0xba, .value = 0x00, }, | ||
| 213 | [45] = { .offset = 0xbb, .value = 0x20, }, | ||
| 214 | [46] = { .offset = 0x10, .value = 0x20, }, | ||
| 215 | [47] = { .offset = 0x11, .value = 0xc8, }, | ||
| 216 | [48] = { .offset = 0x12, .value = 0x02, }, | ||
| 217 | [49] = { .offset = 0x20, .value = 0x00, }, | ||
| 218 | [50] = { .offset = 0x22, .value = 0x00, }, | ||
| 219 | [51] = { .offset = 0x23, .value = 0x00, }, | ||
| 220 | [52] = { .offset = 0x24, .value = 0x00, }, | ||
| 221 | [53] = { .offset = 0x25, .value = 0x00, }, | ||
| 222 | [54] = { .offset = 0x8c, .value = 0x10, }, | ||
| 223 | [55] = { .offset = 0x8d, .value = 0x02, }, | ||
| 224 | [56] = { .offset = 0x8e, .value = 0x04, }, | ||
| 225 | [57] = { .offset = 0x8f, .value = 0x00, }, | ||
| 226 | [58] = { .offset = 0x90, .value = 0xff, }, | ||
| 227 | [59] = { .offset = 0x91, .value = 0x07, }, | ||
| 228 | [60] = { .offset = 0x92, .value = 0xa0, }, | ||
| 229 | [61] = { .offset = 0x93, .value = 0x02, }, | ||
| 230 | [62] = { .offset = 0xa5, .value = 0x00, }, | ||
| 231 | [63] = { .offset = 0xa6, .value = 0x00, }, | ||
| 232 | [64] = { .offset = 0xa7, .value = 0x00, }, | ||
| 233 | [65] = { .offset = 0xa8, .value = 0x00, }, | ||
| 234 | [66] = { .offset = 0xa9, .value = 0x83, }, | ||
| 235 | [67] = { .offset = 0xaa, .value = 0x40, }, | ||
| 236 | [68] = { .offset = 0xab, .value = 0x32, }, | ||
| 237 | [69] = { .offset = 0xac, .value = 0x00, }, | ||
| 238 | [70] = { .offset = 0xa4, .value = 0x80, }, | ||
| 239 | [71] = { .offset = 0x7e, .value = 0x18, }, | ||
| 240 | [72] = { .offset = 0x84, .value = 0x00, }, | ||
| 241 | [73] = { .offset = 0x85, .value = 0x00, }, | ||
| 242 | [74] = { .offset = 0x86, .value = 0x00, }, | ||
| 243 | [75] = { .offset = 0x87, .value = 0x00, }, | ||
| 244 | [76] = { .offset = 0x88, .value = 0x00, }, | ||
| 245 | [77] = { .offset = 0x89, .value = 0x00, }, | ||
| 246 | [78] = { .offset = 0x8a, .value = 0x00, }, | ||
| 247 | [79] = { .offset = 0x8b, .value = 0x00, }, | ||
| 248 | [80] = { .offset = 0x26, .value = 0x00, }, | ||
| 249 | [81] = { .offset = 0x27, .value = 0x00, }, | ||
| 250 | [82] = { .offset = 0xad, .value = 0x00, }, | ||
| 251 | [83] = { .offset = 0x08, .value = 0x30, }, /* 0x31 */ | ||
| 252 | [84] = { .offset = 0x41, .value = 0x00, }, | ||
| 253 | [85] = { .offset = 0xc0, .value = 0x07, }, | ||
| 254 | }, | 269 | }, |
| 255 | [MODE_1024x768] = { | 270 | [MODE_1024x768] = { |
| 256 | [0] = { .offset = 0x0a, .value = 0x81, }, | 271 | .sync = NS2501_C0_ENABLE | NS2501_C0_VSYNC, |
| 257 | [1] = { .offset = 0x18, .value = 0x07, }, | 272 | .conf = NS2501_8_VEN | NS2501_8_HEN | NS2501_8_PD, |
| 258 | [2] = { .offset = 0x19, .value = 0x00, }, | 273 | .syncb = 0x32, |
| 259 | [3] = { .offset = 0x1a, .value = 0x00, }, | 274 | .dither = 0x0f, |
| 260 | [4] = { .offset = 0x1b, .value = 0x11, }, | 275 | .pll_a = 11, |
| 261 | [5] = { .offset = 0x1c, .value = 0x54, }, | 276 | .pll_b = 1350, |
| 262 | [6] = { .offset = 0x1d, .value = 0x03, }, | 277 | .hstart = 276, |
| 263 | [7] = { .offset = 0x1e, .value = 0x02, }, | 278 | .hstop = 1299, |
| 264 | [8] = { .offset = 0xf3, .value = 0x90, }, | 279 | .vstart = 15, |
| 265 | [9] = { .offset = 0xf9, .value = 0x00, }, | 280 | .vstop = 1056, |
| 266 | [10] = { .offset = 0xc1, .value = 0x90, }, | 281 | .vsync = 2047, |
| 267 | [11] = { .offset = 0xc2, .value = 0x00, }, | 282 | .vtotal = 1341, |
| 268 | [12] = { .offset = 0xc3, .value = 0x0f, }, | 283 | .hpos = 0, |
| 269 | [13] = { .offset = 0xc4, .value = 0x03, }, | 284 | .vpos = 7, |
| 270 | [14] = { .offset = 0xc5, .value = 0x16, }, | 285 | .voffs = 27, |
| 271 | [15] = { .offset = 0xc6, .value = 0x00, }, | 286 | .hscale = 65535, |
| 272 | [16] = { .offset = 0xc7, .value = 0x02, }, | 287 | .vscale = 65535 |
| 273 | [17] = { .offset = 0xc8, .value = 0x02, }, | 288 | } |
| 274 | [18] = { .offset = 0xf4, .value = 0x00, }, | 289 | }; |
| 275 | [19] = { .offset = 0x80, .value = 0xff, }, | 290 | |
| 276 | [20] = { .offset = 0x81, .value = 0x07, }, | 291 | /* |
| 277 | [21] = { .offset = 0x82, .value = 0x3d, }, | 292 | * Other configuration values left by the BIOS of the |
| 278 | [22] = { .offset = 0x83, .value = 0x05, }, | 293 | * Fujitsu S6010 in the DVO control registers. Their |
| 279 | [23] = { .offset = 0x94, .value = 0x00, }, | 294 | * value does not depend on the BIOS and their meaning |
| 280 | [24] = { .offset = 0x95, .value = 0x00, }, | 295 | * is unknown. |
| 281 | [25] = { .offset = 0x96, .value = 0x05, }, | 296 | */ |
| 282 | [26] = { .offset = 0x97, .value = 0x00, }, | 297 | |
| 283 | [27] = { .offset = 0x9a, .value = 0x88, }, | 298 | static const struct ns2501_reg mode_agnostic_values[] = { |
| 284 | [28] = { .offset = 0x9b, .value = 0x00, }, | 299 | /* 08 is mode specific */ |
| 285 | [29] = { .offset = 0x98, .value = 0x00, }, | 300 | [0] = { .offset = 0x0a, .value = 0x81, }, |
| 286 | [30] = { .offset = 0x99, .value = 0x00, }, | 301 | /* 10,11 are part of the mode specific configuration */ |
| 287 | [31] = { .offset = 0xf7, .value = 0x88, }, | 302 | [1] = { .offset = 0x12, .value = 0x02, }, |
| 288 | [32] = { .offset = 0xf8, .value = 0x0a, }, | 303 | [2] = { .offset = 0x18, .value = 0x07, }, |
| 289 | [33] = { .offset = 0x9c, .value = 0x24, }, | 304 | [3] = { .offset = 0x19, .value = 0x00, }, |
| 290 | [34] = { .offset = 0x9d, .value = 0x00, }, | 305 | [4] = { .offset = 0x1a, .value = 0x00, }, /* PLL?, ignored */ |
| 291 | [35] = { .offset = 0x9e, .value = 0x25, }, | 306 | /* 1b,1c,1d are part of the mode specific configuration */ |
| 292 | [36] = { .offset = 0x9f, .value = 0x03, }, | 307 | [5] = { .offset = 0x1e, .value = 0x02, }, |
| 293 | [37] = { .offset = 0xa0, .value = 0x28, }, | 308 | [6] = { .offset = 0x1f, .value = 0x40, }, |
| 294 | [38] = { .offset = 0xa1, .value = 0x01, }, | 309 | [7] = { .offset = 0x20, .value = 0x00, }, |
| 295 | [39] = { .offset = 0xa2, .value = 0x28, }, | 310 | [8] = { .offset = 0x21, .value = 0x00, }, |
| 296 | [40] = { .offset = 0xa3, .value = 0x05, }, | 311 | [9] = { .offset = 0x22, .value = 0x00, }, |
| 297 | [41] = { .offset = 0xb6, .value = 0x09, }, | 312 | [10] = { .offset = 0x23, .value = 0x00, }, |
| 298 | [42] = { .offset = 0xb8, .value = 0x00, }, | 313 | [11] = { .offset = 0x24, .value = 0x00, }, |
| 299 | [43] = { .offset = 0xb9, .value = 0xa0, }, | 314 | [12] = { .offset = 0x25, .value = 0x00, }, |
| 300 | [44] = { .offset = 0xba, .value = 0x00, }, | 315 | [13] = { .offset = 0x26, .value = 0x00, }, |
| 301 | [45] = { .offset = 0xbb, .value = 0x20, }, | 316 | [14] = { .offset = 0x27, .value = 0x00, }, |
| 302 | [46] = { .offset = 0x10, .value = 0x00, }, | 317 | [15] = { .offset = 0x7e, .value = 0x18, }, |
| 303 | [47] = { .offset = 0x11, .value = 0xa0, }, | 318 | /* 80-84 are part of the mode-specific configuration */ |
| 304 | [48] = { .offset = 0x12, .value = 0x02, }, | 319 | [16] = { .offset = 0x84, .value = 0x00, }, |
| 305 | [49] = { .offset = 0x20, .value = 0x00, }, | 320 | [17] = { .offset = 0x85, .value = 0x00, }, |
| 306 | [50] = { .offset = 0x22, .value = 0x00, }, | 321 | [18] = { .offset = 0x86, .value = 0x00, }, |
| 307 | [51] = { .offset = 0x23, .value = 0x00, }, | 322 | [19] = { .offset = 0x87, .value = 0x00, }, |
| 308 | [52] = { .offset = 0x24, .value = 0x00, }, | 323 | [20] = { .offset = 0x88, .value = 0x00, }, |
| 309 | [53] = { .offset = 0x25, .value = 0x00, }, | 324 | [21] = { .offset = 0x89, .value = 0x00, }, |
| 310 | [54] = { .offset = 0x8c, .value = 0x10, }, | 325 | [22] = { .offset = 0x8a, .value = 0x00, }, |
| 311 | [55] = { .offset = 0x8d, .value = 0x02, }, | 326 | [23] = { .offset = 0x8b, .value = 0x00, }, |
| 312 | [56] = { .offset = 0x8e, .value = 0x10, }, | 327 | [24] = { .offset = 0x8c, .value = 0x10, }, |
| 313 | [57] = { .offset = 0x8f, .value = 0x00, }, | 328 | [25] = { .offset = 0x8d, .value = 0x02, }, |
| 314 | [58] = { .offset = 0x90, .value = 0xff, }, | 329 | /* 8e,8f are part of the mode-specific configuration */ |
| 315 | [59] = { .offset = 0x91, .value = 0x07, }, | 330 | [26] = { .offset = 0x90, .value = 0xff, }, |
| 316 | [60] = { .offset = 0x92, .value = 0xa0, }, | 331 | [27] = { .offset = 0x91, .value = 0x07, }, |
| 317 | [61] = { .offset = 0x93, .value = 0x02, }, | 332 | [28] = { .offset = 0x92, .value = 0xa0, }, |
| 318 | [62] = { .offset = 0xa5, .value = 0x00, }, | 333 | [29] = { .offset = 0x93, .value = 0x02, }, |
| 319 | [63] = { .offset = 0xa6, .value = 0x00, }, | 334 | [30] = { .offset = 0x94, .value = 0x00, }, |
| 320 | [64] = { .offset = 0xa7, .value = 0x00, }, | 335 | [31] = { .offset = 0x95, .value = 0x00, }, |
| 321 | [65] = { .offset = 0xa8, .value = 0x00, }, | 336 | [32] = { .offset = 0x96, .value = 0x05, }, |
| 322 | [66] = { .offset = 0xa9, .value = 0x04, }, | 337 | [33] = { .offset = 0x97, .value = 0x00, }, |
| 323 | [67] = { .offset = 0xaa, .value = 0x70, }, | 338 | /* 98,99 are part of the mode-specific configuration */ |
| 324 | [68] = { .offset = 0xab, .value = 0x4f, }, | 339 | [34] = { .offset = 0x9a, .value = 0x88, }, |
| 325 | [69] = { .offset = 0xac, .value = 0x00, }, | 340 | [35] = { .offset = 0x9b, .value = 0x00, }, |
| 326 | [70] = { .offset = 0xa4, .value = 0x84, }, | 341 | /* 9c,9d are part of the mode-specific configuration */ |
| 327 | [71] = { .offset = 0x7e, .value = 0x18, }, | 342 | [36] = { .offset = 0x9e, .value = 0x25, }, |
| 328 | [72] = { .offset = 0x84, .value = 0x00, }, | 343 | [37] = { .offset = 0x9f, .value = 0x03, }, |
| 329 | [73] = { .offset = 0x85, .value = 0x00, }, | 344 | [38] = { .offset = 0xa0, .value = 0x28, }, |
| 330 | [74] = { .offset = 0x86, .value = 0x00, }, | 345 | [39] = { .offset = 0xa1, .value = 0x01, }, |
| 331 | [75] = { .offset = 0x87, .value = 0x00, }, | 346 | [40] = { .offset = 0xa2, .value = 0x28, }, |
| 332 | [76] = { .offset = 0x88, .value = 0x00, }, | 347 | [41] = { .offset = 0xa3, .value = 0x05, }, |
| 333 | [77] = { .offset = 0x89, .value = 0x00, }, | 348 | /* register 0xa4 is mode specific, but 0x80..0x84 works always */ |
| 334 | [78] = { .offset = 0x8a, .value = 0x00, }, | 349 | [42] = { .offset = 0xa4, .value = 0x84, }, |
| 335 | [79] = { .offset = 0x8b, .value = 0x00, }, | 350 | [43] = { .offset = 0xa5, .value = 0x00, }, |
| 336 | [80] = { .offset = 0x26, .value = 0x00, }, | 351 | [44] = { .offset = 0xa6, .value = 0x00, }, |
| 337 | [81] = { .offset = 0x27, .value = 0x00, }, | 352 | [45] = { .offset = 0xa7, .value = 0x00, }, |
| 338 | [82] = { .offset = 0xad, .value = 0x00, }, | 353 | [46] = { .offset = 0xa8, .value = 0x00, }, |
| 339 | [83] = { .offset = 0x08, .value = 0x34, }, /* 0x35 */ | 354 | /* 0xa9 to 0xab are mode specific, but have no visible effect */ |
| 340 | [84] = { .offset = 0x41, .value = 0x00, }, | 355 | [47] = { .offset = 0xa9, .value = 0x04, }, |
| 341 | [85] = { .offset = 0xc0, .value = 0x01, }, | 356 | [48] = { .offset = 0xaa, .value = 0x70, }, |
| 342 | }, | 357 | [49] = { .offset = 0xab, .value = 0x4f, }, |
| 358 | [50] = { .offset = 0xac, .value = 0x00, }, | ||
| 359 | [51] = { .offset = 0xad, .value = 0x00, }, | ||
| 360 | [52] = { .offset = 0xb6, .value = 0x09, }, | ||
| 361 | [53] = { .offset = 0xb7, .value = 0x03, }, | ||
| 362 | /* b8,b9 are part of the mode-specific configuration */ | ||
| 363 | [54] = { .offset = 0xba, .value = 0x00, }, | ||
| 364 | [55] = { .offset = 0xbb, .value = 0x20, }, | ||
| 365 | [56] = { .offset = 0xf3, .value = 0x90, }, | ||
| 366 | [57] = { .offset = 0xf4, .value = 0x00, }, | ||
| 367 | [58] = { .offset = 0xf7, .value = 0x88, }, | ||
| 368 | /* f8 is mode specific, but the value does not matter */ | ||
| 369 | [59] = { .offset = 0xf8, .value = 0x0a, }, | ||
| 370 | [60] = { .offset = 0xf9, .value = 0x00, } | ||
| 343 | }; | 371 | }; |
| 344 | 372 | ||
| 345 | static const struct ns2501_reg regs_init[] = { | 373 | static const struct ns2501_reg regs_init[] = { |
| @@ -350,25 +378,12 @@ static const struct ns2501_reg regs_init[] = { | |||
| 350 | 378 | ||
| 351 | struct ns2501_priv { | 379 | struct ns2501_priv { |
| 352 | bool quiet; | 380 | bool quiet; |
| 353 | const struct ns2501_reg *regs; | 381 | const struct ns2501_configuration *conf; |
| 354 | }; | 382 | }; |
| 355 | 383 | ||
| 356 | #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr)) | 384 | #define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr)) |
| 357 | 385 | ||
| 358 | /* | 386 | /* |
| 359 | * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens | ||
| 360 | * laptops does not react on the i2c bus unless | ||
| 361 | * both the PLL is running and the display is configured in its native | ||
| 362 | * resolution. | ||
| 363 | * This function forces the DVO on, and stores the registers it touches. | ||
| 364 | * Afterwards, registers are restored to regular values. | ||
| 365 | * | ||
| 366 | * This is pretty much a hack, though it works. | ||
| 367 | * Without that, ns2501_readb and ns2501_writeb fail | ||
| 368 | * when switching the resolution. | ||
| 369 | */ | ||
| 370 | |||
| 371 | /* | ||
| 372 | ** Read a register from the ns2501. | 387 | ** Read a register from the ns2501. |
| 373 | ** Returns true if successful, false otherwise. | 388 | ** Returns true if successful, false otherwise. |
| 374 | ** If it returns false, it might be wise to enable the | 389 | ** If it returns false, it might be wise to enable the |
| @@ -534,6 +549,7 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, | |||
| 534 | struct drm_display_mode *mode, | 549 | struct drm_display_mode *mode, |
| 535 | struct drm_display_mode *adjusted_mode) | 550 | struct drm_display_mode *adjusted_mode) |
| 536 | { | 551 | { |
| 552 | const struct ns2501_configuration *conf; | ||
| 537 | struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); | 553 | struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv); |
| 538 | int mode_idx, i; | 554 | int mode_idx, i; |
| 539 | 555 | ||
| @@ -541,6 +557,36 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, | |||
| 541 | ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n", | 557 | ("set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n", |
| 542 | mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal); | 558 | mode->hdisplay, mode->htotal, mode->vdisplay, mode->vtotal); |
| 543 | 559 | ||
| 560 | DRM_DEBUG_KMS("Detailed requested mode settings are:\n" | ||
| 561 | "clock : %d kHz\n" | ||
| 562 | "hdisplay : %d\n" | ||
| 563 | "hblank start : %d\n" | ||
| 564 | "hblank end : %d\n" | ||
| 565 | "hsync start : %d\n" | ||
| 566 | "hsync end : %d\n" | ||
| 567 | "htotal : %d\n" | ||
| 568 | "hskew : %d\n" | ||
| 569 | "vdisplay : %d\n" | ||
| 570 | "vblank start : %d\n" | ||
| 571 | "hblank end : %d\n" | ||
| 572 | "vsync start : %d\n" | ||
| 573 | "vsync end : %d\n" | ||
| 574 | "vtotal : %d\n", | ||
| 575 | adjusted_mode->crtc_clock, | ||
| 576 | adjusted_mode->crtc_hdisplay, | ||
| 577 | adjusted_mode->crtc_hblank_start, | ||
| 578 | adjusted_mode->crtc_hblank_end, | ||
| 579 | adjusted_mode->crtc_hsync_start, | ||
| 580 | adjusted_mode->crtc_hsync_end, | ||
| 581 | adjusted_mode->crtc_htotal, | ||
| 582 | adjusted_mode->crtc_hskew, | ||
| 583 | adjusted_mode->crtc_vdisplay, | ||
| 584 | adjusted_mode->crtc_vblank_start, | ||
| 585 | adjusted_mode->crtc_vblank_end, | ||
| 586 | adjusted_mode->crtc_vsync_start, | ||
| 587 | adjusted_mode->crtc_vsync_end, | ||
| 588 | adjusted_mode->crtc_vtotal); | ||
| 589 | |||
| 544 | if (mode->hdisplay == 640 && mode->vdisplay == 480) | 590 | if (mode->hdisplay == 640 && mode->vdisplay == 480) |
| 545 | mode_idx = MODE_640x480; | 591 | mode_idx = MODE_640x480; |
| 546 | else if (mode->hdisplay == 800 && mode->vdisplay == 600) | 592 | else if (mode->hdisplay == 800 && mode->vdisplay == 600) |
| @@ -554,10 +600,44 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo, | |||
| 554 | for (i = 0; i < ARRAY_SIZE(regs_init); i++) | 600 | for (i = 0; i < ARRAY_SIZE(regs_init); i++) |
| 555 | ns2501_writeb(dvo, regs_init[i].offset, regs_init[i].value); | 601 | ns2501_writeb(dvo, regs_init[i].offset, regs_init[i].value); |
| 556 | 602 | ||
| 557 | ns->regs = regs_1024x768[mode_idx]; | 603 | /* Write the mode-agnostic values */ |
| 558 | 604 | for (i = 0; i < ARRAY_SIZE(mode_agnostic_values); i++) | |
| 559 | for (i = 0; i < 84; i++) | 605 | ns2501_writeb(dvo, mode_agnostic_values[i].offset, |
| 560 | ns2501_writeb(dvo, ns->regs[i].offset, ns->regs[i].value); | 606 | mode_agnostic_values[i].value); |
| 607 | |||
| 608 | /* Write now the mode-specific configuration */ | ||
| 609 | conf = ns2501_modes + mode_idx; | ||
| 610 | ns->conf = conf; | ||
| 611 | |||
| 612 | ns2501_writeb(dvo, NS2501_REG8, conf->conf); | ||
| 613 | ns2501_writeb(dvo, NS2501_REG1B, conf->pll_a); | ||
| 614 | ns2501_writeb(dvo, NS2501_REG1C, conf->pll_b & 0xff); | ||
| 615 | ns2501_writeb(dvo, NS2501_REG1D, conf->pll_b >> 8); | ||
| 616 | ns2501_writeb(dvo, NS2501_REGC1, conf->hstart & 0xff); | ||
| 617 | ns2501_writeb(dvo, NS2501_REGC2, conf->hstart >> 8); | ||
| 618 | ns2501_writeb(dvo, NS2501_REGC3, conf->hstop & 0xff); | ||
| 619 | ns2501_writeb(dvo, NS2501_REGC4, conf->hstop >> 8); | ||
| 620 | ns2501_writeb(dvo, NS2501_REGC5, conf->vstart & 0xff); | ||
| 621 | ns2501_writeb(dvo, NS2501_REGC6, conf->vstart >> 8); | ||
| 622 | ns2501_writeb(dvo, NS2501_REGC7, conf->vstop & 0xff); | ||
| 623 | ns2501_writeb(dvo, NS2501_REGC8, conf->vstop >> 8); | ||
| 624 | ns2501_writeb(dvo, NS2501_REG80, conf->vsync & 0xff); | ||
| 625 | ns2501_writeb(dvo, NS2501_REG81, conf->vsync >> 8); | ||
| 626 | ns2501_writeb(dvo, NS2501_REG82, conf->vtotal & 0xff); | ||
| 627 | ns2501_writeb(dvo, NS2501_REG83, conf->vtotal >> 8); | ||
| 628 | ns2501_writeb(dvo, NS2501_REG98, conf->hpos & 0xff); | ||
| 629 | ns2501_writeb(dvo, NS2501_REG99, conf->hpos >> 8); | ||
| 630 | ns2501_writeb(dvo, NS2501_REG8E, conf->vpos & 0xff); | ||
| 631 | ns2501_writeb(dvo, NS2501_REG8F, conf->vpos >> 8); | ||
| 632 | ns2501_writeb(dvo, NS2501_REG9C, conf->voffs & 0xff); | ||
| 633 | ns2501_writeb(dvo, NS2501_REG9D, conf->voffs >> 8); | ||
| 634 | ns2501_writeb(dvo, NS2501_REGB8, conf->hscale & 0xff); | ||
| 635 | ns2501_writeb(dvo, NS2501_REGB9, conf->hscale >> 8); | ||
| 636 | ns2501_writeb(dvo, NS2501_REG10, conf->vscale & 0xff); | ||
| 637 | ns2501_writeb(dvo, NS2501_REG11, conf->vscale >> 8); | ||
| 638 | ns2501_writeb(dvo, NS2501_REGF9, conf->dither); | ||
| 639 | ns2501_writeb(dvo, NS2501_REG41, conf->syncb); | ||
| 640 | ns2501_writeb(dvo, NS2501_REGC0, conf->sync); | ||
| 561 | } | 641 | } |
| 562 | 642 | ||
| 563 | /* set the NS2501 power state */ | 643 | /* set the NS2501 power state */ |
| @@ -579,34 +659,32 @@ static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable) | |||
| 579 | DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable); | 659 | DRM_DEBUG_KMS("Trying set the dpms of the DVO to %i\n", enable); |
| 580 | 660 | ||
| 581 | if (enable) { | 661 | if (enable) { |
| 582 | if (WARN_ON(ns->regs[83].offset != 0x08 || | 662 | ns2501_writeb(dvo, NS2501_REGC0, ns->conf->sync | 0x08); |
| 583 | ns->regs[84].offset != 0x41 || | ||
| 584 | ns->regs[85].offset != 0xc0)) | ||
| 585 | return; | ||
| 586 | |||
| 587 | ns2501_writeb(dvo, 0xc0, ns->regs[85].value | 0x08); | ||
| 588 | 663 | ||
| 589 | ns2501_writeb(dvo, 0x41, ns->regs[84].value); | 664 | ns2501_writeb(dvo, NS2501_REG41, ns->conf->syncb); |
| 590 | 665 | ||
| 591 | ns2501_writeb(dvo, 0x34, 0x01); | 666 | ns2501_writeb(dvo, NS2501_REG34, NS2501_34_ENABLE_OUTPUT); |
| 592 | msleep(15); | 667 | msleep(15); |
| 593 | 668 | ||
| 594 | ns2501_writeb(dvo, 0x08, 0x35); | 669 | ns2501_writeb(dvo, NS2501_REG8, |
| 595 | if (!(ns->regs[83].value & NS2501_8_BPAS)) | 670 | ns->conf->conf | NS2501_8_BPAS); |
| 596 | ns2501_writeb(dvo, 0x08, 0x31); | 671 | if (!(ns->conf->conf & NS2501_8_BPAS)) |
| 672 | ns2501_writeb(dvo, NS2501_REG8, ns->conf->conf); | ||
| 597 | msleep(200); | 673 | msleep(200); |
| 598 | 674 | ||
| 599 | ns2501_writeb(dvo, 0x34, 0x03); | 675 | ns2501_writeb(dvo, NS2501_REG34, |
| 676 | NS2501_34_ENABLE_OUTPUT | NS2501_34_ENABLE_BACKLIGHT); | ||
| 600 | 677 | ||
| 601 | ns2501_writeb(dvo, 0xc0, ns->regs[85].value); | 678 | ns2501_writeb(dvo, NS2501_REGC0, ns->conf->sync); |
| 602 | } else { | 679 | } else { |
| 603 | ns2501_writeb(dvo, 0x34, 0x01); | 680 | ns2501_writeb(dvo, NS2501_REG34, NS2501_34_ENABLE_OUTPUT); |
| 604 | msleep(200); | 681 | msleep(200); |
| 605 | 682 | ||
| 606 | ns2501_writeb(dvo, 0x08, 0x34); | 683 | ns2501_writeb(dvo, NS2501_REG8, NS2501_8_VEN | NS2501_8_HEN | |
| 684 | NS2501_8_BPAS); | ||
| 607 | msleep(15); | 685 | msleep(15); |
| 608 | 686 | ||
| 609 | ns2501_writeb(dvo, 0x34, 0x00); | 687 | ns2501_writeb(dvo, NS2501_REG34, 0x00); |
| 610 | } | 688 | } |
| 611 | } | 689 | } |
| 612 | 690 | ||
