1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2005-2006 Erik Waling
3*4882a593Smuzhiyun * Copyright 2006 Stephane Marchesin
4*4882a593Smuzhiyun * Copyright 2007-2009 Stuart Bennett
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
7*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
8*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
9*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
11*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
14*4882a593Smuzhiyun * all copies or substantial portions of the Software.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*4882a593Smuzhiyun * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20*4882a593Smuzhiyun * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21*4882a593Smuzhiyun * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*4882a593Smuzhiyun * SOFTWARE.
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include "nouveau_drv.h"
26*4882a593Smuzhiyun #include "nouveau_reg.h"
27*4882a593Smuzhiyun #include "dispnv04/hw.h"
28*4882a593Smuzhiyun #include "nouveau_encoder.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <linux/io-mapping.h>
31*4882a593Smuzhiyun #include <linux/firmware.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* these defines are made up */
34*4882a593Smuzhiyun #define NV_CIO_CRE_44_HEADA 0x0
35*4882a593Smuzhiyun #define NV_CIO_CRE_44_HEADB 0x3
36*4882a593Smuzhiyun #define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define EDID1_LEN 128
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip->dev, fmt, ##arg)
41*4882a593Smuzhiyun #define LOG_OLD_VALUE(x)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun struct init_exec {
44*4882a593Smuzhiyun bool execute;
45*4882a593Smuzhiyun bool repeat;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
nv_cksum(const uint8_t * data,unsigned int length)48*4882a593Smuzhiyun static bool nv_cksum(const uint8_t *data, unsigned int length)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * There's a few checksums in the BIOS, so here's a generic checking
52*4882a593Smuzhiyun * function.
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun int i;
55*4882a593Smuzhiyun uint8_t sum = 0;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun for (i = 0; i < length; i++)
58*4882a593Smuzhiyun sum += data[i];
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (sum)
61*4882a593Smuzhiyun return true;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun return false;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
clkcmptable(struct nvbios * bios,uint16_t clktable,int pxclk)66*4882a593Smuzhiyun static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun int compare_record_len, i = 0;
69*4882a593Smuzhiyun uint16_t compareclk, scriptptr = 0;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun if (bios->major_version < 5) /* pre BIT */
72*4882a593Smuzhiyun compare_record_len = 3;
73*4882a593Smuzhiyun else
74*4882a593Smuzhiyun compare_record_len = 4;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun do {
77*4882a593Smuzhiyun compareclk = ROM16(bios->data[clktable + compare_record_len * i]);
78*4882a593Smuzhiyun if (pxclk >= compareclk * 10) {
79*4882a593Smuzhiyun if (bios->major_version < 5) {
80*4882a593Smuzhiyun uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i];
81*4882a593Smuzhiyun scriptptr = ROM16(bios->data[bios->init_script_tbls_ptr + tmdssub * 2]);
82*4882a593Smuzhiyun } else
83*4882a593Smuzhiyun scriptptr = ROM16(bios->data[clktable + 2 + compare_record_len * i]);
84*4882a593Smuzhiyun break;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun i++;
87*4882a593Smuzhiyun } while (compareclk);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun return scriptptr;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun static void
run_digital_op_script(struct drm_device * dev,uint16_t scriptptr,struct dcb_output * dcbent,int head,bool dl)93*4882a593Smuzhiyun run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
94*4882a593Smuzhiyun struct dcb_output *dcbent, int head, bool dl)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun NV_INFO(drm, "0x%04X: Parsing digital output script table\n",
99*4882a593Smuzhiyun scriptptr);
100*4882a593Smuzhiyun NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, head ? NV_CIO_CRE_44_HEADB :
101*4882a593Smuzhiyun NV_CIO_CRE_44_HEADA);
102*4882a593Smuzhiyun nouveau_bios_run_init_table(dev, scriptptr, dcbent, head);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun nv04_dfp_bind_head(dev, dcbent, head, dl);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
call_lvds_manufacturer_script(struct drm_device * dev,struct dcb_output * dcbent,int head,enum LVDS_script script)107*4882a593Smuzhiyun static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
110*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
111*4882a593Smuzhiyun uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & DCB_OUTPUT_C ? 1 : 0);
112*4882a593Smuzhiyun uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun if (!bios->fp.xlated_entry || !sub || !scriptofs)
115*4882a593Smuzhiyun return -EINVAL;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun run_digital_op_script(dev, scriptofs, dcbent, head, bios->fp.dual_link);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (script == LVDS_PANEL_OFF) {
120*4882a593Smuzhiyun /* off-on delay in ms */
121*4882a593Smuzhiyun mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7]));
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun #ifdef __powerpc__
124*4882a593Smuzhiyun /* Powerbook specific quirks */
125*4882a593Smuzhiyun if (script == LVDS_RESET &&
126*4882a593Smuzhiyun (dev->pdev->device == 0x0179 || dev->pdev->device == 0x0189 ||
127*4882a593Smuzhiyun dev->pdev->device == 0x0329))
128*4882a593Smuzhiyun nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
129*4882a593Smuzhiyun #endif
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
run_lvds_table(struct drm_device * dev,struct dcb_output * dcbent,int head,enum LVDS_script script,int pxclk)134*4882a593Smuzhiyun static int run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script, int pxclk)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun * The BIT LVDS table's header has the information to setup the
138*4882a593Smuzhiyun * necessary registers. Following the standard 4 byte header are:
139*4882a593Smuzhiyun * A bitmask byte and a dual-link transition pxclk value for use in
140*4882a593Smuzhiyun * selecting the init script when not using straps; 4 script pointers
141*4882a593Smuzhiyun * for panel power, selected by output and on/off; and 8 table pointers
142*4882a593Smuzhiyun * for panel init, the needed one determined by output, and bits in the
143*4882a593Smuzhiyun * conf byte. These tables are similar to the TMDS tables, consisting
144*4882a593Smuzhiyun * of a list of pxclks and script pointers.
145*4882a593Smuzhiyun */
146*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
147*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
148*4882a593Smuzhiyun unsigned int outputset = (dcbent->or == 4) ? 1 : 0;
149*4882a593Smuzhiyun uint16_t scriptptr = 0, clktable;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /*
152*4882a593Smuzhiyun * For now we assume version 3.0 table - g80 support will need some
153*4882a593Smuzhiyun * changes
154*4882a593Smuzhiyun */
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun switch (script) {
157*4882a593Smuzhiyun case LVDS_INIT:
158*4882a593Smuzhiyun return -ENOSYS;
159*4882a593Smuzhiyun case LVDS_BACKLIGHT_ON:
160*4882a593Smuzhiyun case LVDS_PANEL_ON:
161*4882a593Smuzhiyun scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]);
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun case LVDS_BACKLIGHT_OFF:
164*4882a593Smuzhiyun case LVDS_PANEL_OFF:
165*4882a593Smuzhiyun scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
166*4882a593Smuzhiyun break;
167*4882a593Smuzhiyun case LVDS_RESET:
168*4882a593Smuzhiyun clktable = bios->fp.lvdsmanufacturerpointer + 15;
169*4882a593Smuzhiyun if (dcbent->or == 4)
170*4882a593Smuzhiyun clktable += 8;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun if (dcbent->lvdsconf.use_straps_for_mode) {
173*4882a593Smuzhiyun if (bios->fp.dual_link)
174*4882a593Smuzhiyun clktable += 4;
175*4882a593Smuzhiyun if (bios->fp.if_is_24bit)
176*4882a593Smuzhiyun clktable += 2;
177*4882a593Smuzhiyun } else {
178*4882a593Smuzhiyun /* using EDID */
179*4882a593Smuzhiyun int cmpval_24bit = (dcbent->or == 4) ? 4 : 1;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (bios->fp.dual_link) {
182*4882a593Smuzhiyun clktable += 4;
183*4882a593Smuzhiyun cmpval_24bit <<= 1;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun if (bios->fp.strapless_is_24bit & cmpval_24bit)
187*4882a593Smuzhiyun clktable += 2;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun clktable = ROM16(bios->data[clktable]);
191*4882a593Smuzhiyun if (!clktable) {
192*4882a593Smuzhiyun NV_ERROR(drm, "Pixel clock comparison table not found\n");
193*4882a593Smuzhiyun return -ENOENT;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun scriptptr = clkcmptable(bios, clktable, pxclk);
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (!scriptptr) {
199*4882a593Smuzhiyun NV_ERROR(drm, "LVDS output init script not found\n");
200*4882a593Smuzhiyun return -ENOENT;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun return 0;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
call_lvds_script(struct drm_device * dev,struct dcb_output * dcbent,int head,enum LVDS_script script,int pxclk)207*4882a593Smuzhiyun int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script, int pxclk)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun /*
210*4882a593Smuzhiyun * LVDS operations are multiplexed in an effort to present a single API
211*4882a593Smuzhiyun * which works with two vastly differing underlying structures.
212*4882a593Smuzhiyun * This acts as the demux
213*4882a593Smuzhiyun */
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
216*4882a593Smuzhiyun struct nvif_object *device = &drm->client.device.object;
217*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
218*4882a593Smuzhiyun uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
219*4882a593Smuzhiyun uint32_t sel_clk_binding, sel_clk;
220*4882a593Smuzhiyun int ret;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (bios->fp.last_script_invoc == (script << 1 | head) || !lvds_ver ||
223*4882a593Smuzhiyun (lvds_ver >= 0x30 && script == LVDS_INIT))
224*4882a593Smuzhiyun return 0;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun if (!bios->fp.lvds_init_run) {
227*4882a593Smuzhiyun bios->fp.lvds_init_run = true;
228*4882a593Smuzhiyun call_lvds_script(dev, dcbent, head, LVDS_INIT, pxclk);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change)
232*4882a593Smuzhiyun call_lvds_script(dev, dcbent, head, LVDS_RESET, pxclk);
233*4882a593Smuzhiyun if (script == LVDS_RESET && bios->fp.power_off_for_reset)
234*4882a593Smuzhiyun call_lvds_script(dev, dcbent, head, LVDS_PANEL_OFF, pxclk);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun NV_INFO(drm, "Calling LVDS script %d:\n", script);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /* don't let script change pll->head binding */
239*4882a593Smuzhiyun sel_clk_binding = nvif_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun if (lvds_ver < 0x30)
242*4882a593Smuzhiyun ret = call_lvds_manufacturer_script(dev, dcbent, head, script);
243*4882a593Smuzhiyun else
244*4882a593Smuzhiyun ret = run_lvds_table(dev, dcbent, head, script, pxclk);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun bios->fp.last_script_invoc = (script << 1 | head);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
249*4882a593Smuzhiyun NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
250*4882a593Smuzhiyun /* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */
251*4882a593Smuzhiyun nvif_wr32(device, NV_PBUS_POWERCTRL_2, 0);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun return ret;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun struct lvdstableheader {
257*4882a593Smuzhiyun uint8_t lvds_ver, headerlen, recordlen;
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun
parse_lvds_manufacturer_table_header(struct drm_device * dev,struct nvbios * bios,struct lvdstableheader * lth)260*4882a593Smuzhiyun static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct nvbios *bios, struct lvdstableheader *lth)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun /*
263*4882a593Smuzhiyun * BMP version (0xa) LVDS table has a simple header of version and
264*4882a593Smuzhiyun * record length. The BIT LVDS table has the typical BIT table header:
265*4882a593Smuzhiyun * version byte, header length byte, record length byte, and a byte for
266*4882a593Smuzhiyun * the maximum number of records that can be held in the table.
267*4882a593Smuzhiyun */
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
270*4882a593Smuzhiyun uint8_t lvds_ver, headerlen, recordlen;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun memset(lth, 0, sizeof(struct lvdstableheader));
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun if (bios->fp.lvdsmanufacturerpointer == 0x0) {
275*4882a593Smuzhiyun NV_ERROR(drm, "Pointer to LVDS manufacturer table invalid\n");
276*4882a593Smuzhiyun return -EINVAL;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun switch (lvds_ver) {
282*4882a593Smuzhiyun case 0x0a: /* pre NV40 */
283*4882a593Smuzhiyun headerlen = 2;
284*4882a593Smuzhiyun recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
285*4882a593Smuzhiyun break;
286*4882a593Smuzhiyun case 0x30: /* NV4x */
287*4882a593Smuzhiyun headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
288*4882a593Smuzhiyun if (headerlen < 0x1f) {
289*4882a593Smuzhiyun NV_ERROR(drm, "LVDS table header not understood\n");
290*4882a593Smuzhiyun return -EINVAL;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
293*4882a593Smuzhiyun break;
294*4882a593Smuzhiyun case 0x40: /* G80/G90 */
295*4882a593Smuzhiyun headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
296*4882a593Smuzhiyun if (headerlen < 0x7) {
297*4882a593Smuzhiyun NV_ERROR(drm, "LVDS table header not understood\n");
298*4882a593Smuzhiyun return -EINVAL;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
301*4882a593Smuzhiyun break;
302*4882a593Smuzhiyun default:
303*4882a593Smuzhiyun NV_ERROR(drm,
304*4882a593Smuzhiyun "LVDS table revision %d.%d not currently supported\n",
305*4882a593Smuzhiyun lvds_ver >> 4, lvds_ver & 0xf);
306*4882a593Smuzhiyun return -ENOSYS;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun lth->lvds_ver = lvds_ver;
310*4882a593Smuzhiyun lth->headerlen = headerlen;
311*4882a593Smuzhiyun lth->recordlen = recordlen;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun return 0;
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun static int
get_fp_strap(struct drm_device * dev,struct nvbios * bios)317*4882a593Smuzhiyun get_fp_strap(struct drm_device *dev, struct nvbios *bios)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
320*4882a593Smuzhiyun struct nvif_object *device = &drm->client.device.object;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun /*
323*4882a593Smuzhiyun * The fp strap is normally dictated by the "User Strap" in
324*4882a593Smuzhiyun * PEXTDEV_BOOT_0[20:16], but on BMP cards when bit 2 of the
325*4882a593Smuzhiyun * Internal_Flags struct at 0x48 is set, the user strap gets overriden
326*4882a593Smuzhiyun * by the PCI subsystem ID during POST, but not before the previous user
327*4882a593Smuzhiyun * strap has been committed to CR58 for CR57=0xf on head A, which may be
328*4882a593Smuzhiyun * read and used instead
329*4882a593Smuzhiyun */
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (bios->major_version < 5 && bios->data[0x48] & 0x4)
332*4882a593Smuzhiyun return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_MAXWELL)
335*4882a593Smuzhiyun return nvif_rd32(device, 0x001800) & 0x0000000f;
336*4882a593Smuzhiyun else
337*4882a593Smuzhiyun if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA)
338*4882a593Smuzhiyun return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
339*4882a593Smuzhiyun else
340*4882a593Smuzhiyun return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
parse_fp_mode_table(struct drm_device * dev,struct nvbios * bios)343*4882a593Smuzhiyun static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
346*4882a593Smuzhiyun uint8_t *fptable;
347*4882a593Smuzhiyun uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex;
348*4882a593Smuzhiyun int ret, ofs, fpstrapping;
349*4882a593Smuzhiyun struct lvdstableheader lth;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun if (bios->fp.fptablepointer == 0x0) {
352*4882a593Smuzhiyun /* Most laptop cards lack an fp table. They use DDC. */
353*4882a593Smuzhiyun NV_DEBUG(drm, "Pointer to flat panel table invalid\n");
354*4882a593Smuzhiyun bios->digital_min_front_porch = 0x4b;
355*4882a593Smuzhiyun return 0;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun fptable = &bios->data[bios->fp.fptablepointer];
359*4882a593Smuzhiyun fptable_ver = fptable[0];
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun switch (fptable_ver) {
362*4882a593Smuzhiyun /*
363*4882a593Smuzhiyun * BMP version 0x5.0x11 BIOSen have version 1 like tables, but no
364*4882a593Smuzhiyun * version field, and miss one of the spread spectrum/PWM bytes.
365*4882a593Smuzhiyun * This could affect early GF2Go parts (not seen any appropriate ROMs
366*4882a593Smuzhiyun * though). Here we assume that a version of 0x05 matches this case
367*4882a593Smuzhiyun * (combining with a BMP version check would be better), as the
368*4882a593Smuzhiyun * common case for the panel type field is 0x0005, and that is in
369*4882a593Smuzhiyun * fact what we are reading the first byte of.
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun case 0x05: /* some NV10, 11, 15, 16 */
372*4882a593Smuzhiyun recordlen = 42;
373*4882a593Smuzhiyun ofs = -1;
374*4882a593Smuzhiyun break;
375*4882a593Smuzhiyun case 0x10: /* some NV15/16, and NV11+ */
376*4882a593Smuzhiyun recordlen = 44;
377*4882a593Smuzhiyun ofs = 0;
378*4882a593Smuzhiyun break;
379*4882a593Smuzhiyun case 0x20: /* NV40+ */
380*4882a593Smuzhiyun headerlen = fptable[1];
381*4882a593Smuzhiyun recordlen = fptable[2];
382*4882a593Smuzhiyun fpentries = fptable[3];
383*4882a593Smuzhiyun /*
384*4882a593Smuzhiyun * fptable[4] is the minimum
385*4882a593Smuzhiyun * RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap
386*4882a593Smuzhiyun */
387*4882a593Smuzhiyun bios->digital_min_front_porch = fptable[4];
388*4882a593Smuzhiyun ofs = -7;
389*4882a593Smuzhiyun break;
390*4882a593Smuzhiyun default:
391*4882a593Smuzhiyun NV_ERROR(drm,
392*4882a593Smuzhiyun "FP table revision %d.%d not currently supported\n",
393*4882a593Smuzhiyun fptable_ver >> 4, fptable_ver & 0xf);
394*4882a593Smuzhiyun return -ENOSYS;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun if (!bios->is_mobile) /* !mobile only needs digital_min_front_porch */
398*4882a593Smuzhiyun return 0;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun ret = parse_lvds_manufacturer_table_header(dev, bios, <h);
401*4882a593Smuzhiyun if (ret)
402*4882a593Smuzhiyun return ret;
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (lth.lvds_ver == 0x30 || lth.lvds_ver == 0x40) {
405*4882a593Smuzhiyun bios->fp.fpxlatetableptr = bios->fp.lvdsmanufacturerpointer +
406*4882a593Smuzhiyun lth.headerlen + 1;
407*4882a593Smuzhiyun bios->fp.xlatwidth = lth.recordlen;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun if (bios->fp.fpxlatetableptr == 0x0) {
410*4882a593Smuzhiyun NV_ERROR(drm, "Pointer to flat panel xlat table invalid\n");
411*4882a593Smuzhiyun return -EINVAL;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun fpstrapping = get_fp_strap(dev, bios);
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun fpindex = bios->data[bios->fp.fpxlatetableptr +
417*4882a593Smuzhiyun fpstrapping * bios->fp.xlatwidth];
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun if (fpindex > fpentries) {
420*4882a593Smuzhiyun NV_ERROR(drm, "Bad flat panel table index\n");
421*4882a593Smuzhiyun return -ENOENT;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /* nv4x cards need both a strap value and fpindex of 0xf to use DDC */
425*4882a593Smuzhiyun if (lth.lvds_ver > 0x10)
426*4882a593Smuzhiyun bios->fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /*
429*4882a593Smuzhiyun * If either the strap or xlated fpindex value are 0xf there is no
430*4882a593Smuzhiyun * panel using a strap-derived bios mode present. this condition
431*4882a593Smuzhiyun * includes, but is different from, the DDC panel indicator above
432*4882a593Smuzhiyun */
433*4882a593Smuzhiyun if (fpstrapping == 0xf || fpindex == 0xf)
434*4882a593Smuzhiyun return 0;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen +
437*4882a593Smuzhiyun recordlen * fpindex + ofs;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun NV_INFO(drm, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n",
440*4882a593Smuzhiyun ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1,
441*4882a593Smuzhiyun ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1,
442*4882a593Smuzhiyun ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun return 0;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun
nouveau_bios_fp_mode(struct drm_device * dev,struct drm_display_mode * mode)447*4882a593Smuzhiyun bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
450*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
451*4882a593Smuzhiyun uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr];
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun if (!mode) /* just checking whether we can produce a mode */
454*4882a593Smuzhiyun return bios->fp.mode_ptr;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun memset(mode, 0, sizeof(struct drm_display_mode));
457*4882a593Smuzhiyun /*
458*4882a593Smuzhiyun * For version 1.0 (version in byte 0):
459*4882a593Smuzhiyun * bytes 1-2 are "panel type", including bits on whether Colour/mono,
460*4882a593Smuzhiyun * single/dual link, and type (TFT etc.)
461*4882a593Smuzhiyun * bytes 3-6 are bits per colour in RGBX
462*4882a593Smuzhiyun */
463*4882a593Smuzhiyun mode->clock = ROM16(mode_entry[7]) * 10;
464*4882a593Smuzhiyun /* bytes 9-10 is HActive */
465*4882a593Smuzhiyun mode->hdisplay = ROM16(mode_entry[11]) + 1;
466*4882a593Smuzhiyun /*
467*4882a593Smuzhiyun * bytes 13-14 is HValid Start
468*4882a593Smuzhiyun * bytes 15-16 is HValid End
469*4882a593Smuzhiyun */
470*4882a593Smuzhiyun mode->hsync_start = ROM16(mode_entry[17]) + 1;
471*4882a593Smuzhiyun mode->hsync_end = ROM16(mode_entry[19]) + 1;
472*4882a593Smuzhiyun mode->htotal = ROM16(mode_entry[21]) + 1;
473*4882a593Smuzhiyun /* bytes 23-24, 27-30 similarly, but vertical */
474*4882a593Smuzhiyun mode->vdisplay = ROM16(mode_entry[25]) + 1;
475*4882a593Smuzhiyun mode->vsync_start = ROM16(mode_entry[31]) + 1;
476*4882a593Smuzhiyun mode->vsync_end = ROM16(mode_entry[33]) + 1;
477*4882a593Smuzhiyun mode->vtotal = ROM16(mode_entry[35]) + 1;
478*4882a593Smuzhiyun mode->flags |= (mode_entry[37] & 0x10) ?
479*4882a593Smuzhiyun DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
480*4882a593Smuzhiyun mode->flags |= (mode_entry[37] & 0x1) ?
481*4882a593Smuzhiyun DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun * bytes 38-39 relate to spread spectrum settings
484*4882a593Smuzhiyun * bytes 40-43 are something to do with PWM
485*4882a593Smuzhiyun */
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun mode->status = MODE_OK;
488*4882a593Smuzhiyun mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
489*4882a593Smuzhiyun drm_mode_set_name(mode);
490*4882a593Smuzhiyun return bios->fp.mode_ptr;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
nouveau_bios_parse_lvds_table(struct drm_device * dev,int pxclk,bool * dl,bool * if_is_24bit)493*4882a593Smuzhiyun int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, bool *if_is_24bit)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun /*
496*4882a593Smuzhiyun * The LVDS table header is (mostly) described in
497*4882a593Smuzhiyun * parse_lvds_manufacturer_table_header(): the BIT header additionally
498*4882a593Smuzhiyun * contains the dual-link transition pxclk (in 10s kHz), at byte 5 - if
499*4882a593Smuzhiyun * straps are not being used for the panel, this specifies the frequency
500*4882a593Smuzhiyun * at which modes should be set up in the dual link style.
501*4882a593Smuzhiyun *
502*4882a593Smuzhiyun * Following the header, the BMP (ver 0xa) table has several records,
503*4882a593Smuzhiyun * indexed by a separate xlat table, indexed in turn by the fp strap in
504*4882a593Smuzhiyun * EXTDEV_BOOT. Each record had a config byte, followed by 6 script
505*4882a593Smuzhiyun * numbers for use by INIT_SUB which controlled panel init and power,
506*4882a593Smuzhiyun * and finally a dword of ms to sleep between power off and on
507*4882a593Smuzhiyun * operations.
508*4882a593Smuzhiyun *
509*4882a593Smuzhiyun * In the BIT versions, the table following the header serves as an
510*4882a593Smuzhiyun * integrated config and xlat table: the records in the table are
511*4882a593Smuzhiyun * indexed by the FP strap nibble in EXTDEV_BOOT, and each record has
512*4882a593Smuzhiyun * two bytes - the first as a config byte, the second for indexing the
513*4882a593Smuzhiyun * fp mode table pointed to by the BIT 'D' table
514*4882a593Smuzhiyun *
515*4882a593Smuzhiyun * DDC is not used until after card init, so selecting the correct table
516*4882a593Smuzhiyun * entry and setting the dual link flag for EDID equipped panels,
517*4882a593Smuzhiyun * requiring tests against the native-mode pixel clock, cannot be done
518*4882a593Smuzhiyun * until later, when this function should be called with non-zero pxclk
519*4882a593Smuzhiyun */
520*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
521*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
522*4882a593Smuzhiyun int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0;
523*4882a593Smuzhiyun struct lvdstableheader lth;
524*4882a593Smuzhiyun uint16_t lvdsofs;
525*4882a593Smuzhiyun int ret, chip_version = bios->chip_version;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun ret = parse_lvds_manufacturer_table_header(dev, bios, <h);
528*4882a593Smuzhiyun if (ret)
529*4882a593Smuzhiyun return ret;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun switch (lth.lvds_ver) {
532*4882a593Smuzhiyun case 0x0a: /* pre NV40 */
533*4882a593Smuzhiyun lvdsmanufacturerindex = bios->data[
534*4882a593Smuzhiyun bios->fp.fpxlatemanufacturertableptr +
535*4882a593Smuzhiyun fpstrapping];
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun /* we're done if this isn't the EDID panel case */
538*4882a593Smuzhiyun if (!pxclk)
539*4882a593Smuzhiyun break;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun if (chip_version < 0x25) {
542*4882a593Smuzhiyun /* nv17 behaviour
543*4882a593Smuzhiyun *
544*4882a593Smuzhiyun * It seems the old style lvds script pointer is reused
545*4882a593Smuzhiyun * to select 18/24 bit colour depth for EDID panels.
546*4882a593Smuzhiyun */
547*4882a593Smuzhiyun lvdsmanufacturerindex =
548*4882a593Smuzhiyun (bios->legacy.lvds_single_a_script_ptr & 1) ?
549*4882a593Smuzhiyun 2 : 0;
550*4882a593Smuzhiyun if (pxclk >= bios->fp.duallink_transition_clk)
551*4882a593Smuzhiyun lvdsmanufacturerindex++;
552*4882a593Smuzhiyun } else if (chip_version < 0x30) {
553*4882a593Smuzhiyun /* nv28 behaviour (off-chip encoder)
554*4882a593Smuzhiyun *
555*4882a593Smuzhiyun * nv28 does a complex dance of first using byte 121 of
556*4882a593Smuzhiyun * the EDID to choose the lvdsmanufacturerindex, then
557*4882a593Smuzhiyun * later attempting to match the EDID manufacturer and
558*4882a593Smuzhiyun * product IDs in a table (signature 'pidt' (panel id
559*4882a593Smuzhiyun * table?)), setting an lvdsmanufacturerindex of 0 and
560*4882a593Smuzhiyun * an fp strap of the match index (or 0xf if none)
561*4882a593Smuzhiyun */
562*4882a593Smuzhiyun lvdsmanufacturerindex = 0;
563*4882a593Smuzhiyun } else {
564*4882a593Smuzhiyun /* nv31, nv34 behaviour */
565*4882a593Smuzhiyun lvdsmanufacturerindex = 0;
566*4882a593Smuzhiyun if (pxclk >= bios->fp.duallink_transition_clk)
567*4882a593Smuzhiyun lvdsmanufacturerindex = 2;
568*4882a593Smuzhiyun if (pxclk >= 140000)
569*4882a593Smuzhiyun lvdsmanufacturerindex = 3;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun /*
573*4882a593Smuzhiyun * nvidia set the high nibble of (cr57=f, cr58) to
574*4882a593Smuzhiyun * lvdsmanufacturerindex in this case; we don't
575*4882a593Smuzhiyun */
576*4882a593Smuzhiyun break;
577*4882a593Smuzhiyun case 0x30: /* NV4x */
578*4882a593Smuzhiyun case 0x40: /* G80/G90 */
579*4882a593Smuzhiyun lvdsmanufacturerindex = fpstrapping;
580*4882a593Smuzhiyun break;
581*4882a593Smuzhiyun default:
582*4882a593Smuzhiyun NV_ERROR(drm, "LVDS table revision not currently supported\n");
583*4882a593Smuzhiyun return -ENOSYS;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + lth.headerlen + lth.recordlen * lvdsmanufacturerindex;
587*4882a593Smuzhiyun switch (lth.lvds_ver) {
588*4882a593Smuzhiyun case 0x0a:
589*4882a593Smuzhiyun bios->fp.power_off_for_reset = bios->data[lvdsofs] & 1;
590*4882a593Smuzhiyun bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2;
591*4882a593Smuzhiyun bios->fp.dual_link = bios->data[lvdsofs] & 4;
592*4882a593Smuzhiyun bios->fp.link_c_increment = bios->data[lvdsofs] & 8;
593*4882a593Smuzhiyun *if_is_24bit = bios->data[lvdsofs] & 16;
594*4882a593Smuzhiyun break;
595*4882a593Smuzhiyun case 0x30:
596*4882a593Smuzhiyun case 0x40:
597*4882a593Smuzhiyun /*
598*4882a593Smuzhiyun * No sign of the "power off for reset" or "reset for panel
599*4882a593Smuzhiyun * on" bits, but it's safer to assume we should
600*4882a593Smuzhiyun */
601*4882a593Smuzhiyun bios->fp.power_off_for_reset = true;
602*4882a593Smuzhiyun bios->fp.reset_after_pclk_change = true;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun /*
605*4882a593Smuzhiyun * It's ok lvdsofs is wrong for nv4x edid case; dual_link is
606*4882a593Smuzhiyun * over-written, and if_is_24bit isn't used
607*4882a593Smuzhiyun */
608*4882a593Smuzhiyun bios->fp.dual_link = bios->data[lvdsofs] & 1;
609*4882a593Smuzhiyun bios->fp.if_is_24bit = bios->data[lvdsofs] & 2;
610*4882a593Smuzhiyun bios->fp.strapless_is_24bit = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
611*4882a593Smuzhiyun bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
612*4882a593Smuzhiyun break;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun /* set dual_link flag for EDID case */
616*4882a593Smuzhiyun if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
617*4882a593Smuzhiyun bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk);
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun *dl = bios->fp.dual_link;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun return 0;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
run_tmds_table(struct drm_device * dev,struct dcb_output * dcbent,int head,int pxclk)624*4882a593Smuzhiyun int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun /*
627*4882a593Smuzhiyun * the pxclk parameter is in kHz
628*4882a593Smuzhiyun *
629*4882a593Smuzhiyun * This runs the TMDS regs setting code found on BIT bios cards
630*4882a593Smuzhiyun *
631*4882a593Smuzhiyun * For ffs(or) == 1 use the first table, for ffs(or) == 2 and
632*4882a593Smuzhiyun * ffs(or) == 3, use the second.
633*4882a593Smuzhiyun */
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
636*4882a593Smuzhiyun struct nvif_object *device = &drm->client.device.object;
637*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
638*4882a593Smuzhiyun int cv = bios->chip_version;
639*4882a593Smuzhiyun uint16_t clktable = 0, scriptptr;
640*4882a593Smuzhiyun uint32_t sel_clk_binding, sel_clk;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun /* pre-nv17 off-chip tmds uses scripts, post nv17 doesn't */
643*4882a593Smuzhiyun if (cv >= 0x17 && cv != 0x1a && cv != 0x20 &&
644*4882a593Smuzhiyun dcbent->location != DCB_LOC_ON_CHIP)
645*4882a593Smuzhiyun return 0;
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun switch (ffs(dcbent->or)) {
648*4882a593Smuzhiyun case 1:
649*4882a593Smuzhiyun clktable = bios->tmds.output0_script_ptr;
650*4882a593Smuzhiyun break;
651*4882a593Smuzhiyun case 2:
652*4882a593Smuzhiyun case 3:
653*4882a593Smuzhiyun clktable = bios->tmds.output1_script_ptr;
654*4882a593Smuzhiyun break;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (!clktable) {
658*4882a593Smuzhiyun NV_ERROR(drm, "Pixel clock comparison table not found\n");
659*4882a593Smuzhiyun return -EINVAL;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun scriptptr = clkcmptable(bios, clktable, pxclk);
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun if (!scriptptr) {
665*4882a593Smuzhiyun NV_ERROR(drm, "TMDS output init script not found\n");
666*4882a593Smuzhiyun return -ENOENT;
667*4882a593Smuzhiyun }
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /* don't let script change pll->head binding */
670*4882a593Smuzhiyun sel_clk_binding = nvif_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000;
671*4882a593Smuzhiyun run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000);
672*4882a593Smuzhiyun sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
673*4882a593Smuzhiyun NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun return 0;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun
parse_script_table_pointers(struct nvbios * bios,uint16_t offset)678*4882a593Smuzhiyun static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun /*
681*4882a593Smuzhiyun * Parses the init table segment for pointers used in script execution.
682*4882a593Smuzhiyun *
683*4882a593Smuzhiyun * offset + 0 (16 bits): init script tables pointer
684*4882a593Smuzhiyun * offset + 2 (16 bits): macro index table pointer
685*4882a593Smuzhiyun * offset + 4 (16 bits): macro table pointer
686*4882a593Smuzhiyun * offset + 6 (16 bits): condition table pointer
687*4882a593Smuzhiyun * offset + 8 (16 bits): io condition table pointer
688*4882a593Smuzhiyun * offset + 10 (16 bits): io flag condition table pointer
689*4882a593Smuzhiyun * offset + 12 (16 bits): init function table pointer
690*4882a593Smuzhiyun */
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun bios->init_script_tbls_ptr = ROM16(bios->data[offset]);
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
parse_bit_A_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)695*4882a593Smuzhiyun static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun /*
698*4882a593Smuzhiyun * Parses the load detect values for g80 cards.
699*4882a593Smuzhiyun *
700*4882a593Smuzhiyun * offset + 0 (16 bits): loadval table pointer
701*4882a593Smuzhiyun */
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
704*4882a593Smuzhiyun uint16_t load_table_ptr;
705*4882a593Smuzhiyun uint8_t version, headerlen, entrylen, num_entries;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun if (bitentry->length != 3) {
708*4882a593Smuzhiyun NV_ERROR(drm, "Do not understand BIT A table\n");
709*4882a593Smuzhiyun return -EINVAL;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun load_table_ptr = ROM16(bios->data[bitentry->offset]);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun if (load_table_ptr == 0x0) {
715*4882a593Smuzhiyun NV_DEBUG(drm, "Pointer to BIT loadval table invalid\n");
716*4882a593Smuzhiyun return -EINVAL;
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun version = bios->data[load_table_ptr];
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun if (version != 0x10) {
722*4882a593Smuzhiyun NV_ERROR(drm, "BIT loadval table version %d.%d not supported\n",
723*4882a593Smuzhiyun version >> 4, version & 0xF);
724*4882a593Smuzhiyun return -ENOSYS;
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun headerlen = bios->data[load_table_ptr + 1];
728*4882a593Smuzhiyun entrylen = bios->data[load_table_ptr + 2];
729*4882a593Smuzhiyun num_entries = bios->data[load_table_ptr + 3];
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun if (headerlen != 4 || entrylen != 4 || num_entries != 2) {
732*4882a593Smuzhiyun NV_ERROR(drm, "Do not understand BIT loadval table\n");
733*4882a593Smuzhiyun return -EINVAL;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /* First entry is normal dac, 2nd tv-out perhaps? */
737*4882a593Smuzhiyun bios->dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun return 0;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
parse_bit_display_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)742*4882a593Smuzhiyun static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
743*4882a593Smuzhiyun {
744*4882a593Smuzhiyun /*
745*4882a593Smuzhiyun * Parses the flat panel table segment that the bit entry points to.
746*4882a593Smuzhiyun * Starting at bitentry->offset:
747*4882a593Smuzhiyun *
748*4882a593Smuzhiyun * offset + 0 (16 bits): ??? table pointer - seems to have 18 byte
749*4882a593Smuzhiyun * records beginning with a freq.
750*4882a593Smuzhiyun * offset + 2 (16 bits): mode table pointer
751*4882a593Smuzhiyun */
752*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (bitentry->length != 4) {
755*4882a593Smuzhiyun NV_ERROR(drm, "Do not understand BIT display table\n");
756*4882a593Smuzhiyun return -EINVAL;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun bios->fp.fptablepointer = ROM16(bios->data[bitentry->offset + 2]);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun return 0;
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun
parse_bit_init_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)764*4882a593Smuzhiyun static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun /*
767*4882a593Smuzhiyun * Parses the init table segment that the bit entry points to.
768*4882a593Smuzhiyun *
769*4882a593Smuzhiyun * See parse_script_table_pointers for layout
770*4882a593Smuzhiyun */
771*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun if (bitentry->length < 14) {
774*4882a593Smuzhiyun NV_ERROR(drm, "Do not understand init table\n");
775*4882a593Smuzhiyun return -EINVAL;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun parse_script_table_pointers(bios, bitentry->offset);
779*4882a593Smuzhiyun return 0;
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun
parse_bit_i_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)782*4882a593Smuzhiyun static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun /*
785*4882a593Smuzhiyun * BIT 'i' (info?) table
786*4882a593Smuzhiyun *
787*4882a593Smuzhiyun * offset + 0 (32 bits): BIOS version dword (as in B table)
788*4882a593Smuzhiyun * offset + 5 (8 bits): BIOS feature byte (same as for BMP?)
789*4882a593Smuzhiyun * offset + 13 (16 bits): pointer to table containing DAC load
790*4882a593Smuzhiyun * detection comparison values
791*4882a593Smuzhiyun *
792*4882a593Smuzhiyun * There's other things in the table, purpose unknown
793*4882a593Smuzhiyun */
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
796*4882a593Smuzhiyun uint16_t daccmpoffset;
797*4882a593Smuzhiyun uint8_t dacver, dacheaderlen;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (bitentry->length < 6) {
800*4882a593Smuzhiyun NV_ERROR(drm, "BIT i table too short for needed information\n");
801*4882a593Smuzhiyun return -EINVAL;
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun /*
805*4882a593Smuzhiyun * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's
806*4882a593Smuzhiyun * Quadro identity crisis), other bits possibly as for BMP feature byte
807*4882a593Smuzhiyun */
808*4882a593Smuzhiyun bios->feature_byte = bios->data[bitentry->offset + 5];
809*4882a593Smuzhiyun bios->is_mobile = bios->feature_byte & FEATURE_MOBILE;
810*4882a593Smuzhiyun
811*4882a593Smuzhiyun if (bitentry->length < 15) {
812*4882a593Smuzhiyun NV_WARN(drm, "BIT i table not long enough for DAC load "
813*4882a593Smuzhiyun "detection comparison table\n");
814*4882a593Smuzhiyun return -EINVAL;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun daccmpoffset = ROM16(bios->data[bitentry->offset + 13]);
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun /* doesn't exist on g80 */
820*4882a593Smuzhiyun if (!daccmpoffset)
821*4882a593Smuzhiyun return 0;
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun /*
824*4882a593Smuzhiyun * The first value in the table, following the header, is the
825*4882a593Smuzhiyun * comparison value, the second entry is a comparison value for
826*4882a593Smuzhiyun * TV load detection.
827*4882a593Smuzhiyun */
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun dacver = bios->data[daccmpoffset];
830*4882a593Smuzhiyun dacheaderlen = bios->data[daccmpoffset + 1];
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun if (dacver != 0x00 && dacver != 0x10) {
833*4882a593Smuzhiyun NV_WARN(drm, "DAC load detection comparison table version "
834*4882a593Smuzhiyun "%d.%d not known\n", dacver >> 4, dacver & 0xf);
835*4882a593Smuzhiyun return -ENOSYS;
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun bios->dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
839*4882a593Smuzhiyun bios->tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]);
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun return 0;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
parse_bit_lvds_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)844*4882a593Smuzhiyun static int parse_bit_lvds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun /*
847*4882a593Smuzhiyun * Parses the LVDS table segment that the bit entry points to.
848*4882a593Smuzhiyun * Starting at bitentry->offset:
849*4882a593Smuzhiyun *
850*4882a593Smuzhiyun * offset + 0 (16 bits): LVDS strap xlate table pointer
851*4882a593Smuzhiyun */
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun if (bitentry->length != 2) {
856*4882a593Smuzhiyun NV_ERROR(drm, "Do not understand BIT LVDS table\n");
857*4882a593Smuzhiyun return -EINVAL;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun /*
861*4882a593Smuzhiyun * No idea if it's still called the LVDS manufacturer table, but
862*4882a593Smuzhiyun * the concept's close enough.
863*4882a593Smuzhiyun */
864*4882a593Smuzhiyun bios->fp.lvdsmanufacturerpointer = ROM16(bios->data[bitentry->offset]);
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun return 0;
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun static int
parse_bit_M_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)870*4882a593Smuzhiyun parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios,
871*4882a593Smuzhiyun struct bit_entry *bitentry)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun /*
874*4882a593Smuzhiyun * offset + 2 (8 bits): number of options in an
875*4882a593Smuzhiyun * INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set
876*4882a593Smuzhiyun * offset + 3 (16 bits): pointer to strap xlate table for RAM
877*4882a593Smuzhiyun * restrict option selection
878*4882a593Smuzhiyun *
879*4882a593Smuzhiyun * There's a bunch of bits in this table other than the RAM restrict
880*4882a593Smuzhiyun * stuff that we don't use - their use currently unknown
881*4882a593Smuzhiyun */
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun /*
884*4882a593Smuzhiyun * Older bios versions don't have a sufficiently long table for
885*4882a593Smuzhiyun * what we want
886*4882a593Smuzhiyun */
887*4882a593Smuzhiyun if (bitentry->length < 0x5)
888*4882a593Smuzhiyun return 0;
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun if (bitentry->version < 2) {
891*4882a593Smuzhiyun bios->ram_restrict_group_count = bios->data[bitentry->offset + 2];
892*4882a593Smuzhiyun bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]);
893*4882a593Smuzhiyun } else {
894*4882a593Smuzhiyun bios->ram_restrict_group_count = bios->data[bitentry->offset + 0];
895*4882a593Smuzhiyun bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 1]);
896*4882a593Smuzhiyun }
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun return 0;
899*4882a593Smuzhiyun }
900*4882a593Smuzhiyun
parse_bit_tmds_tbl_entry(struct drm_device * dev,struct nvbios * bios,struct bit_entry * bitentry)901*4882a593Smuzhiyun static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry)
902*4882a593Smuzhiyun {
903*4882a593Smuzhiyun /*
904*4882a593Smuzhiyun * Parses the pointer to the TMDS table
905*4882a593Smuzhiyun *
906*4882a593Smuzhiyun * Starting at bitentry->offset:
907*4882a593Smuzhiyun *
908*4882a593Smuzhiyun * offset + 0 (16 bits): TMDS table pointer
909*4882a593Smuzhiyun *
910*4882a593Smuzhiyun * The TMDS table is typically found just before the DCB table, with a
911*4882a593Smuzhiyun * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being
912*4882a593Smuzhiyun * length?)
913*4882a593Smuzhiyun *
914*4882a593Smuzhiyun * At offset +7 is a pointer to a script, which I don't know how to
915*4882a593Smuzhiyun * run yet.
916*4882a593Smuzhiyun * At offset +9 is a pointer to another script, likewise
917*4882a593Smuzhiyun * Offset +11 has a pointer to a table where the first word is a pxclk
918*4882a593Smuzhiyun * frequency and the second word a pointer to a script, which should be
919*4882a593Smuzhiyun * run if the comparison pxclk frequency is less than the pxclk desired.
920*4882a593Smuzhiyun * This repeats for decreasing comparison frequencies
921*4882a593Smuzhiyun * Offset +13 has a pointer to a similar table
922*4882a593Smuzhiyun * The selection of table (and possibly +7/+9 script) is dictated by
923*4882a593Smuzhiyun * "or" from the DCB.
924*4882a593Smuzhiyun */
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
927*4882a593Smuzhiyun uint16_t tmdstableptr, script1, script2;
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun if (bitentry->length != 2) {
930*4882a593Smuzhiyun NV_ERROR(drm, "Do not understand BIT TMDS table\n");
931*4882a593Smuzhiyun return -EINVAL;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun tmdstableptr = ROM16(bios->data[bitentry->offset]);
935*4882a593Smuzhiyun if (!tmdstableptr) {
936*4882a593Smuzhiyun NV_INFO(drm, "Pointer to TMDS table not found\n");
937*4882a593Smuzhiyun return -EINVAL;
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun NV_INFO(drm, "TMDS table version %d.%d\n",
941*4882a593Smuzhiyun bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun /* nv50+ has v2.0, but we don't parse it atm */
944*4882a593Smuzhiyun if (bios->data[tmdstableptr] != 0x11)
945*4882a593Smuzhiyun return -ENOSYS;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun /*
948*4882a593Smuzhiyun * These two scripts are odd: they don't seem to get run even when
949*4882a593Smuzhiyun * they are not stubbed.
950*4882a593Smuzhiyun */
951*4882a593Smuzhiyun script1 = ROM16(bios->data[tmdstableptr + 7]);
952*4882a593Smuzhiyun script2 = ROM16(bios->data[tmdstableptr + 9]);
953*4882a593Smuzhiyun if (bios->data[script1] != 'q' || bios->data[script2] != 'q')
954*4882a593Smuzhiyun NV_WARN(drm, "TMDS table script pointers not stubbed\n");
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]);
957*4882a593Smuzhiyun bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]);
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun return 0;
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun struct bit_table {
963*4882a593Smuzhiyun const char id;
964*4882a593Smuzhiyun int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *);
965*4882a593Smuzhiyun };
966*4882a593Smuzhiyun
967*4882a593Smuzhiyun #define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry })
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun int
bit_table(struct drm_device * dev,u8 id,struct bit_entry * bit)970*4882a593Smuzhiyun bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit)
971*4882a593Smuzhiyun {
972*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
973*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
974*4882a593Smuzhiyun u8 entries, *entry;
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun if (bios->type != NVBIOS_BIT)
977*4882a593Smuzhiyun return -ENODEV;
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun entries = bios->data[bios->offset + 10];
980*4882a593Smuzhiyun entry = &bios->data[bios->offset + 12];
981*4882a593Smuzhiyun while (entries--) {
982*4882a593Smuzhiyun if (entry[0] == id) {
983*4882a593Smuzhiyun bit->id = entry[0];
984*4882a593Smuzhiyun bit->version = entry[1];
985*4882a593Smuzhiyun bit->length = ROM16(entry[2]);
986*4882a593Smuzhiyun bit->offset = ROM16(entry[4]);
987*4882a593Smuzhiyun bit->data = ROMPTR(dev, entry[4]);
988*4882a593Smuzhiyun return 0;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun entry += bios->data[bios->offset + 9];
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun return -ENOENT;
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun static int
parse_bit_table(struct nvbios * bios,const uint16_t bitoffset,struct bit_table * table)998*4882a593Smuzhiyun parse_bit_table(struct nvbios *bios, const uint16_t bitoffset,
999*4882a593Smuzhiyun struct bit_table *table)
1000*4882a593Smuzhiyun {
1001*4882a593Smuzhiyun struct drm_device *dev = bios->dev;
1002*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1003*4882a593Smuzhiyun struct bit_entry bitentry;
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun if (bit_table(dev, table->id, &bitentry) == 0)
1006*4882a593Smuzhiyun return table->parse_fn(dev, bios, &bitentry);
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun NV_INFO(drm, "BIT table '%c' not found\n", table->id);
1009*4882a593Smuzhiyun return -ENOSYS;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun static int
parse_bit_structure(struct nvbios * bios,const uint16_t bitoffset)1013*4882a593Smuzhiyun parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset)
1014*4882a593Smuzhiyun {
1015*4882a593Smuzhiyun int ret;
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun /*
1018*4882a593Smuzhiyun * The only restriction on parsing order currently is having 'i' first
1019*4882a593Smuzhiyun * for use of bios->*_version or bios->feature_byte while parsing;
1020*4882a593Smuzhiyun * functions shouldn't be actually *doing* anything apart from pulling
1021*4882a593Smuzhiyun * data from the image into the bios struct, thus no interdependencies
1022*4882a593Smuzhiyun */
1023*4882a593Smuzhiyun ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('i', i));
1024*4882a593Smuzhiyun if (ret) /* info? */
1025*4882a593Smuzhiyun return ret;
1026*4882a593Smuzhiyun if (bios->major_version >= 0x60) /* g80+ */
1027*4882a593Smuzhiyun parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A));
1028*4882a593Smuzhiyun parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display));
1029*4882a593Smuzhiyun ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init));
1030*4882a593Smuzhiyun if (ret)
1031*4882a593Smuzhiyun return ret;
1032*4882a593Smuzhiyun parse_bit_table(bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */
1033*4882a593Smuzhiyun parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds));
1034*4882a593Smuzhiyun parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds));
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun return 0;
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun
parse_bmp_structure(struct drm_device * dev,struct nvbios * bios,unsigned int offset)1039*4882a593Smuzhiyun static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsigned int offset)
1040*4882a593Smuzhiyun {
1041*4882a593Smuzhiyun /*
1042*4882a593Smuzhiyun * Parses the BMP structure for useful things, but does not act on them
1043*4882a593Smuzhiyun *
1044*4882a593Smuzhiyun * offset + 5: BMP major version
1045*4882a593Smuzhiyun * offset + 6: BMP minor version
1046*4882a593Smuzhiyun * offset + 9: BMP feature byte
1047*4882a593Smuzhiyun * offset + 10: BCD encoded BIOS version
1048*4882a593Smuzhiyun *
1049*4882a593Smuzhiyun * offset + 18: init script table pointer (for bios versions < 5.10h)
1050*4882a593Smuzhiyun * offset + 20: extra init script table pointer (for bios
1051*4882a593Smuzhiyun * versions < 5.10h)
1052*4882a593Smuzhiyun *
1053*4882a593Smuzhiyun * offset + 24: memory init table pointer (used on early bios versions)
1054*4882a593Smuzhiyun * offset + 26: SDR memory sequencing setup data table
1055*4882a593Smuzhiyun * offset + 28: DDR memory sequencing setup data table
1056*4882a593Smuzhiyun *
1057*4882a593Smuzhiyun * offset + 54: index of I2C CRTC pair to use for CRT output
1058*4882a593Smuzhiyun * offset + 55: index of I2C CRTC pair to use for TV output
1059*4882a593Smuzhiyun * offset + 56: index of I2C CRTC pair to use for flat panel output
1060*4882a593Smuzhiyun * offset + 58: write CRTC index for I2C pair 0
1061*4882a593Smuzhiyun * offset + 59: read CRTC index for I2C pair 0
1062*4882a593Smuzhiyun * offset + 60: write CRTC index for I2C pair 1
1063*4882a593Smuzhiyun * offset + 61: read CRTC index for I2C pair 1
1064*4882a593Smuzhiyun *
1065*4882a593Smuzhiyun * offset + 67: maximum internal PLL frequency (single stage PLL)
1066*4882a593Smuzhiyun * offset + 71: minimum internal PLL frequency (single stage PLL)
1067*4882a593Smuzhiyun *
1068*4882a593Smuzhiyun * offset + 75: script table pointers, as described in
1069*4882a593Smuzhiyun * parse_script_table_pointers
1070*4882a593Smuzhiyun *
1071*4882a593Smuzhiyun * offset + 89: TMDS single link output A table pointer
1072*4882a593Smuzhiyun * offset + 91: TMDS single link output B table pointer
1073*4882a593Smuzhiyun * offset + 95: LVDS single link output A table pointer
1074*4882a593Smuzhiyun * offset + 105: flat panel timings table pointer
1075*4882a593Smuzhiyun * offset + 107: flat panel strapping translation table pointer
1076*4882a593Smuzhiyun * offset + 117: LVDS manufacturer panel config table pointer
1077*4882a593Smuzhiyun * offset + 119: LVDS manufacturer strapping translation table pointer
1078*4882a593Smuzhiyun *
1079*4882a593Smuzhiyun * offset + 142: PLL limits table pointer
1080*4882a593Smuzhiyun *
1081*4882a593Smuzhiyun * offset + 156: minimum pixel clock for LVDS dual link
1082*4882a593Smuzhiyun */
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1085*4882a593Smuzhiyun uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor;
1086*4882a593Smuzhiyun uint16_t bmplength;
1087*4882a593Smuzhiyun uint16_t legacy_scripts_offset, legacy_i2c_offset;
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun /* load needed defaults in case we can't parse this info */
1090*4882a593Smuzhiyun bios->digital_min_front_porch = 0x4b;
1091*4882a593Smuzhiyun bios->fmaxvco = 256000;
1092*4882a593Smuzhiyun bios->fminvco = 128000;
1093*4882a593Smuzhiyun bios->fp.duallink_transition_clk = 90000;
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun bmp_version_major = bmp[5];
1096*4882a593Smuzhiyun bmp_version_minor = bmp[6];
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun NV_INFO(drm, "BMP version %d.%d\n",
1099*4882a593Smuzhiyun bmp_version_major, bmp_version_minor);
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun /*
1102*4882a593Smuzhiyun * Make sure that 0x36 is blank and can't be mistaken for a DCB
1103*4882a593Smuzhiyun * pointer on early versions
1104*4882a593Smuzhiyun */
1105*4882a593Smuzhiyun if (bmp_version_major < 5)
1106*4882a593Smuzhiyun *(uint16_t *)&bios->data[0x36] = 0;
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun /*
1109*4882a593Smuzhiyun * Seems that the minor version was 1 for all major versions prior
1110*4882a593Smuzhiyun * to 5. Version 6 could theoretically exist, but I suspect BIT
1111*4882a593Smuzhiyun * happened instead.
1112*4882a593Smuzhiyun */
1113*4882a593Smuzhiyun if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) {
1114*4882a593Smuzhiyun NV_ERROR(drm, "You have an unsupported BMP version. "
1115*4882a593Smuzhiyun "Please send in your bios\n");
1116*4882a593Smuzhiyun return -ENOSYS;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun if (bmp_version_major == 0)
1120*4882a593Smuzhiyun /* nothing that's currently useful in this version */
1121*4882a593Smuzhiyun return 0;
1122*4882a593Smuzhiyun else if (bmp_version_major == 1)
1123*4882a593Smuzhiyun bmplength = 44; /* exact for 1.01 */
1124*4882a593Smuzhiyun else if (bmp_version_major == 2)
1125*4882a593Smuzhiyun bmplength = 48; /* exact for 2.01 */
1126*4882a593Smuzhiyun else if (bmp_version_major == 3)
1127*4882a593Smuzhiyun bmplength = 54;
1128*4882a593Smuzhiyun /* guessed - mem init tables added in this version */
1129*4882a593Smuzhiyun else if (bmp_version_major == 4 || bmp_version_minor < 0x1)
1130*4882a593Smuzhiyun /* don't know if 5.0 exists... */
1131*4882a593Smuzhiyun bmplength = 62;
1132*4882a593Smuzhiyun /* guessed - BMP I2C indices added in version 4*/
1133*4882a593Smuzhiyun else if (bmp_version_minor < 0x6)
1134*4882a593Smuzhiyun bmplength = 67; /* exact for 5.01 */
1135*4882a593Smuzhiyun else if (bmp_version_minor < 0x10)
1136*4882a593Smuzhiyun bmplength = 75; /* exact for 5.06 */
1137*4882a593Smuzhiyun else if (bmp_version_minor == 0x10)
1138*4882a593Smuzhiyun bmplength = 89; /* exact for 5.10h */
1139*4882a593Smuzhiyun else if (bmp_version_minor < 0x14)
1140*4882a593Smuzhiyun bmplength = 118; /* exact for 5.11h */
1141*4882a593Smuzhiyun else if (bmp_version_minor < 0x24)
1142*4882a593Smuzhiyun /*
1143*4882a593Smuzhiyun * Not sure of version where pll limits came in;
1144*4882a593Smuzhiyun * certainly exist by 0x24 though.
1145*4882a593Smuzhiyun */
1146*4882a593Smuzhiyun /* length not exact: this is long enough to get lvds members */
1147*4882a593Smuzhiyun bmplength = 123;
1148*4882a593Smuzhiyun else if (bmp_version_minor < 0x27)
1149*4882a593Smuzhiyun /*
1150*4882a593Smuzhiyun * Length not exact: this is long enough to get pll limit
1151*4882a593Smuzhiyun * member
1152*4882a593Smuzhiyun */
1153*4882a593Smuzhiyun bmplength = 144;
1154*4882a593Smuzhiyun else
1155*4882a593Smuzhiyun /*
1156*4882a593Smuzhiyun * Length not exact: this is long enough to get dual link
1157*4882a593Smuzhiyun * transition clock.
1158*4882a593Smuzhiyun */
1159*4882a593Smuzhiyun bmplength = 158;
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun /* checksum */
1162*4882a593Smuzhiyun if (nv_cksum(bmp, 8)) {
1163*4882a593Smuzhiyun NV_ERROR(drm, "Bad BMP checksum\n");
1164*4882a593Smuzhiyun return -EINVAL;
1165*4882a593Smuzhiyun }
1166*4882a593Smuzhiyun
1167*4882a593Smuzhiyun /*
1168*4882a593Smuzhiyun * Bit 4 seems to indicate either a mobile bios or a quadro card --
1169*4882a593Smuzhiyun * mobile behaviour consistent (nv11+), quadro only seen nv18gl-nv36gl
1170*4882a593Smuzhiyun * (not nv10gl), bit 5 that the flat panel tables are present, and
1171*4882a593Smuzhiyun * bit 6 a tv bios.
1172*4882a593Smuzhiyun */
1173*4882a593Smuzhiyun bios->feature_byte = bmp[9];
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun if (bmp_version_major < 5 || bmp_version_minor < 0x10)
1176*4882a593Smuzhiyun bios->old_style_init = true;
1177*4882a593Smuzhiyun legacy_scripts_offset = 18;
1178*4882a593Smuzhiyun if (bmp_version_major < 2)
1179*4882a593Smuzhiyun legacy_scripts_offset -= 4;
1180*4882a593Smuzhiyun bios->init_script_tbls_ptr = ROM16(bmp[legacy_scripts_offset]);
1181*4882a593Smuzhiyun bios->extra_init_script_tbl_ptr = ROM16(bmp[legacy_scripts_offset + 2]);
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun if (bmp_version_major > 2) { /* appears in BMP 3 */
1184*4882a593Smuzhiyun bios->legacy.mem_init_tbl_ptr = ROM16(bmp[24]);
1185*4882a593Smuzhiyun bios->legacy.sdr_seq_tbl_ptr = ROM16(bmp[26]);
1186*4882a593Smuzhiyun bios->legacy.ddr_seq_tbl_ptr = ROM16(bmp[28]);
1187*4882a593Smuzhiyun }
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun legacy_i2c_offset = 0x48; /* BMP version 2 & 3 */
1190*4882a593Smuzhiyun if (bmplength > 61)
1191*4882a593Smuzhiyun legacy_i2c_offset = offset + 54;
1192*4882a593Smuzhiyun bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
1193*4882a593Smuzhiyun bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
1194*4882a593Smuzhiyun bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun if (bmplength > 74) {
1197*4882a593Smuzhiyun bios->fmaxvco = ROM32(bmp[67]);
1198*4882a593Smuzhiyun bios->fminvco = ROM32(bmp[71]);
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun if (bmplength > 88)
1201*4882a593Smuzhiyun parse_script_table_pointers(bios, offset + 75);
1202*4882a593Smuzhiyun if (bmplength > 94) {
1203*4882a593Smuzhiyun bios->tmds.output0_script_ptr = ROM16(bmp[89]);
1204*4882a593Smuzhiyun bios->tmds.output1_script_ptr = ROM16(bmp[91]);
1205*4882a593Smuzhiyun /*
1206*4882a593Smuzhiyun * Never observed in use with lvds scripts, but is reused for
1207*4882a593Smuzhiyun * 18/24 bit panel interface default for EDID equipped panels
1208*4882a593Smuzhiyun * (if_is_24bit not set directly to avoid any oscillation).
1209*4882a593Smuzhiyun */
1210*4882a593Smuzhiyun bios->legacy.lvds_single_a_script_ptr = ROM16(bmp[95]);
1211*4882a593Smuzhiyun }
1212*4882a593Smuzhiyun if (bmplength > 108) {
1213*4882a593Smuzhiyun bios->fp.fptablepointer = ROM16(bmp[105]);
1214*4882a593Smuzhiyun bios->fp.fpxlatetableptr = ROM16(bmp[107]);
1215*4882a593Smuzhiyun bios->fp.xlatwidth = 1;
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun if (bmplength > 120) {
1218*4882a593Smuzhiyun bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]);
1219*4882a593Smuzhiyun bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]);
1220*4882a593Smuzhiyun }
1221*4882a593Smuzhiyun #if 0
1222*4882a593Smuzhiyun if (bmplength > 143)
1223*4882a593Smuzhiyun bios->pll_limit_tbl_ptr = ROM16(bmp[142]);
1224*4882a593Smuzhiyun #endif
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun if (bmplength > 157)
1227*4882a593Smuzhiyun bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun return 0;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
findstr(uint8_t * data,int n,const uint8_t * str,int len)1232*4882a593Smuzhiyun static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
1233*4882a593Smuzhiyun {
1234*4882a593Smuzhiyun int i, j;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun for (i = 0; i <= (n - len); i++) {
1237*4882a593Smuzhiyun for (j = 0; j < len; j++)
1238*4882a593Smuzhiyun if (data[i + j] != str[j])
1239*4882a593Smuzhiyun break;
1240*4882a593Smuzhiyun if (j == len)
1241*4882a593Smuzhiyun return i;
1242*4882a593Smuzhiyun }
1243*4882a593Smuzhiyun
1244*4882a593Smuzhiyun return 0;
1245*4882a593Smuzhiyun }
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun void *
olddcb_table(struct drm_device * dev)1248*4882a593Smuzhiyun olddcb_table(struct drm_device *dev)
1249*4882a593Smuzhiyun {
1250*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1251*4882a593Smuzhiyun u8 *dcb = NULL;
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun if (drm->client.device.info.family > NV_DEVICE_INFO_V0_TNT)
1254*4882a593Smuzhiyun dcb = ROMPTR(dev, drm->vbios.data[0x36]);
1255*4882a593Smuzhiyun if (!dcb) {
1256*4882a593Smuzhiyun NV_WARN(drm, "No DCB data found in VBIOS\n");
1257*4882a593Smuzhiyun return NULL;
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun if (dcb[0] >= 0x42) {
1261*4882a593Smuzhiyun NV_WARN(drm, "DCB version 0x%02x unknown\n", dcb[0]);
1262*4882a593Smuzhiyun return NULL;
1263*4882a593Smuzhiyun } else
1264*4882a593Smuzhiyun if (dcb[0] >= 0x30) {
1265*4882a593Smuzhiyun if (ROM32(dcb[6]) == 0x4edcbdcb)
1266*4882a593Smuzhiyun return dcb;
1267*4882a593Smuzhiyun } else
1268*4882a593Smuzhiyun if (dcb[0] >= 0x20) {
1269*4882a593Smuzhiyun if (ROM32(dcb[4]) == 0x4edcbdcb)
1270*4882a593Smuzhiyun return dcb;
1271*4882a593Smuzhiyun } else
1272*4882a593Smuzhiyun if (dcb[0] >= 0x15) {
1273*4882a593Smuzhiyun if (!memcmp(&dcb[-7], "DEV_REC", 7))
1274*4882a593Smuzhiyun return dcb;
1275*4882a593Smuzhiyun } else {
1276*4882a593Smuzhiyun /*
1277*4882a593Smuzhiyun * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but
1278*4882a593Smuzhiyun * always has the same single (crt) entry, even when tv-out
1279*4882a593Smuzhiyun * present, so the conclusion is this version cannot really
1280*4882a593Smuzhiyun * be used.
1281*4882a593Smuzhiyun *
1282*4882a593Smuzhiyun * v1.2 tables (some NV6/10, and NV15+) normally have the
1283*4882a593Smuzhiyun * same 5 entries, which are not specific to the card and so
1284*4882a593Smuzhiyun * no use.
1285*4882a593Smuzhiyun *
1286*4882a593Smuzhiyun * v1.2 does have an I2C table that read_dcb_i2c_table can
1287*4882a593Smuzhiyun * handle, but cards exist (nv11 in #14821) with a bad i2c
1288*4882a593Smuzhiyun * table pointer, so use the indices parsed in
1289*4882a593Smuzhiyun * parse_bmp_structure.
1290*4882a593Smuzhiyun *
1291*4882a593Smuzhiyun * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
1292*4882a593Smuzhiyun */
1293*4882a593Smuzhiyun NV_WARN(drm, "No useful DCB data in VBIOS\n");
1294*4882a593Smuzhiyun return NULL;
1295*4882a593Smuzhiyun }
1296*4882a593Smuzhiyun
1297*4882a593Smuzhiyun NV_WARN(drm, "DCB header validation failed\n");
1298*4882a593Smuzhiyun return NULL;
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun void *
olddcb_outp(struct drm_device * dev,u8 idx)1302*4882a593Smuzhiyun olddcb_outp(struct drm_device *dev, u8 idx)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun u8 *dcb = olddcb_table(dev);
1305*4882a593Smuzhiyun if (dcb && dcb[0] >= 0x30) {
1306*4882a593Smuzhiyun if (idx < dcb[2])
1307*4882a593Smuzhiyun return dcb + dcb[1] + (idx * dcb[3]);
1308*4882a593Smuzhiyun } else
1309*4882a593Smuzhiyun if (dcb && dcb[0] >= 0x20) {
1310*4882a593Smuzhiyun u8 *i2c = ROMPTR(dev, dcb[2]);
1311*4882a593Smuzhiyun u8 *ent = dcb + 8 + (idx * 8);
1312*4882a593Smuzhiyun if (i2c && ent < i2c)
1313*4882a593Smuzhiyun return ent;
1314*4882a593Smuzhiyun } else
1315*4882a593Smuzhiyun if (dcb && dcb[0] >= 0x15) {
1316*4882a593Smuzhiyun u8 *i2c = ROMPTR(dev, dcb[2]);
1317*4882a593Smuzhiyun u8 *ent = dcb + 4 + (idx * 10);
1318*4882a593Smuzhiyun if (i2c && ent < i2c)
1319*4882a593Smuzhiyun return ent;
1320*4882a593Smuzhiyun }
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun return NULL;
1323*4882a593Smuzhiyun }
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun int
olddcb_outp_foreach(struct drm_device * dev,void * data,int (* exec)(struct drm_device *,void *,int idx,u8 * outp))1326*4882a593Smuzhiyun olddcb_outp_foreach(struct drm_device *dev, void *data,
1327*4882a593Smuzhiyun int (*exec)(struct drm_device *, void *, int idx, u8 *outp))
1328*4882a593Smuzhiyun {
1329*4882a593Smuzhiyun int ret, idx = -1;
1330*4882a593Smuzhiyun u8 *outp = NULL;
1331*4882a593Smuzhiyun while ((outp = olddcb_outp(dev, ++idx))) {
1332*4882a593Smuzhiyun if (ROM32(outp[0]) == 0x00000000)
1333*4882a593Smuzhiyun break; /* seen on an NV11 with DCB v1.5 */
1334*4882a593Smuzhiyun if (ROM32(outp[0]) == 0xffffffff)
1335*4882a593Smuzhiyun break; /* seen on an NV17 with DCB v2.0 */
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun if ((outp[0] & 0x0f) == DCB_OUTPUT_UNUSED)
1338*4882a593Smuzhiyun continue;
1339*4882a593Smuzhiyun if ((outp[0] & 0x0f) == DCB_OUTPUT_EOL)
1340*4882a593Smuzhiyun break;
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun ret = exec(dev, data, idx, outp);
1343*4882a593Smuzhiyun if (ret)
1344*4882a593Smuzhiyun return ret;
1345*4882a593Smuzhiyun }
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun return 0;
1348*4882a593Smuzhiyun }
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun u8 *
olddcb_conntab(struct drm_device * dev)1351*4882a593Smuzhiyun olddcb_conntab(struct drm_device *dev)
1352*4882a593Smuzhiyun {
1353*4882a593Smuzhiyun u8 *dcb = olddcb_table(dev);
1354*4882a593Smuzhiyun if (dcb && dcb[0] >= 0x30 && dcb[1] >= 0x16) {
1355*4882a593Smuzhiyun u8 *conntab = ROMPTR(dev, dcb[0x14]);
1356*4882a593Smuzhiyun if (conntab && conntab[0] >= 0x30 && conntab[0] <= 0x40)
1357*4882a593Smuzhiyun return conntab;
1358*4882a593Smuzhiyun }
1359*4882a593Smuzhiyun return NULL;
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun u8 *
olddcb_conn(struct drm_device * dev,u8 idx)1363*4882a593Smuzhiyun olddcb_conn(struct drm_device *dev, u8 idx)
1364*4882a593Smuzhiyun {
1365*4882a593Smuzhiyun u8 *conntab = olddcb_conntab(dev);
1366*4882a593Smuzhiyun if (conntab && idx < conntab[2])
1367*4882a593Smuzhiyun return conntab + conntab[1] + (idx * conntab[3]);
1368*4882a593Smuzhiyun return NULL;
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun
new_dcb_entry(struct dcb_table * dcb)1371*4882a593Smuzhiyun static struct dcb_output *new_dcb_entry(struct dcb_table *dcb)
1372*4882a593Smuzhiyun {
1373*4882a593Smuzhiyun struct dcb_output *entry = &dcb->entry[dcb->entries];
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun memset(entry, 0, sizeof(struct dcb_output));
1376*4882a593Smuzhiyun entry->index = dcb->entries++;
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun return entry;
1379*4882a593Smuzhiyun }
1380*4882a593Smuzhiyun
fabricate_dcb_output(struct dcb_table * dcb,int type,int i2c,int heads,int or)1381*4882a593Smuzhiyun static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c,
1382*4882a593Smuzhiyun int heads, int or)
1383*4882a593Smuzhiyun {
1384*4882a593Smuzhiyun struct dcb_output *entry = new_dcb_entry(dcb);
1385*4882a593Smuzhiyun
1386*4882a593Smuzhiyun entry->type = type;
1387*4882a593Smuzhiyun entry->i2c_index = i2c;
1388*4882a593Smuzhiyun entry->heads = heads;
1389*4882a593Smuzhiyun if (type != DCB_OUTPUT_ANALOG)
1390*4882a593Smuzhiyun entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
1391*4882a593Smuzhiyun entry->or = or;
1392*4882a593Smuzhiyun }
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun static bool
parse_dcb20_entry(struct drm_device * dev,struct dcb_table * dcb,uint32_t conn,uint32_t conf,struct dcb_output * entry)1395*4882a593Smuzhiyun parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
1396*4882a593Smuzhiyun uint32_t conn, uint32_t conf, struct dcb_output *entry)
1397*4882a593Smuzhiyun {
1398*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1399*4882a593Smuzhiyun int link = 0;
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun entry->type = conn & 0xf;
1402*4882a593Smuzhiyun entry->i2c_index = (conn >> 4) & 0xf;
1403*4882a593Smuzhiyun entry->heads = (conn >> 8) & 0xf;
1404*4882a593Smuzhiyun entry->connector = (conn >> 12) & 0xf;
1405*4882a593Smuzhiyun entry->bus = (conn >> 16) & 0xf;
1406*4882a593Smuzhiyun entry->location = (conn >> 20) & 0x3;
1407*4882a593Smuzhiyun entry->or = (conn >> 24) & 0xf;
1408*4882a593Smuzhiyun
1409*4882a593Smuzhiyun switch (entry->type) {
1410*4882a593Smuzhiyun case DCB_OUTPUT_ANALOG:
1411*4882a593Smuzhiyun /*
1412*4882a593Smuzhiyun * Although the rest of a CRT conf dword is usually
1413*4882a593Smuzhiyun * zeros, mac biosen have stuff there so we must mask
1414*4882a593Smuzhiyun */
1415*4882a593Smuzhiyun entry->crtconf.maxfreq = (dcb->version < 0x30) ?
1416*4882a593Smuzhiyun (conf & 0xffff) * 10 :
1417*4882a593Smuzhiyun (conf & 0xff) * 10000;
1418*4882a593Smuzhiyun break;
1419*4882a593Smuzhiyun case DCB_OUTPUT_LVDS:
1420*4882a593Smuzhiyun {
1421*4882a593Smuzhiyun uint32_t mask;
1422*4882a593Smuzhiyun if (conf & 0x1)
1423*4882a593Smuzhiyun entry->lvdsconf.use_straps_for_mode = true;
1424*4882a593Smuzhiyun if (dcb->version < 0x22) {
1425*4882a593Smuzhiyun mask = ~0xd;
1426*4882a593Smuzhiyun /*
1427*4882a593Smuzhiyun * The laptop in bug 14567 lies and claims to not use
1428*4882a593Smuzhiyun * straps when it does, so assume all DCB 2.0 laptops
1429*4882a593Smuzhiyun * use straps, until a broken EDID using one is produced
1430*4882a593Smuzhiyun */
1431*4882a593Smuzhiyun entry->lvdsconf.use_straps_for_mode = true;
1432*4882a593Smuzhiyun /*
1433*4882a593Smuzhiyun * Both 0x4 and 0x8 show up in v2.0 tables; assume they
1434*4882a593Smuzhiyun * mean the same thing (probably wrong, but might work)
1435*4882a593Smuzhiyun */
1436*4882a593Smuzhiyun if (conf & 0x4 || conf & 0x8)
1437*4882a593Smuzhiyun entry->lvdsconf.use_power_scripts = true;
1438*4882a593Smuzhiyun } else {
1439*4882a593Smuzhiyun mask = ~0x7;
1440*4882a593Smuzhiyun if (conf & 0x2)
1441*4882a593Smuzhiyun entry->lvdsconf.use_acpi_for_edid = true;
1442*4882a593Smuzhiyun if (conf & 0x4)
1443*4882a593Smuzhiyun entry->lvdsconf.use_power_scripts = true;
1444*4882a593Smuzhiyun entry->lvdsconf.sor.link = (conf & 0x00000030) >> 4;
1445*4882a593Smuzhiyun link = entry->lvdsconf.sor.link;
1446*4882a593Smuzhiyun }
1447*4882a593Smuzhiyun if (conf & mask) {
1448*4882a593Smuzhiyun /*
1449*4882a593Smuzhiyun * Until we even try to use these on G8x, it's
1450*4882a593Smuzhiyun * useless reporting unknown bits. They all are.
1451*4882a593Smuzhiyun */
1452*4882a593Smuzhiyun if (dcb->version >= 0x40)
1453*4882a593Smuzhiyun break;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun NV_ERROR(drm, "Unknown LVDS configuration bits, "
1456*4882a593Smuzhiyun "please report\n");
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun break;
1459*4882a593Smuzhiyun }
1460*4882a593Smuzhiyun case DCB_OUTPUT_TV:
1461*4882a593Smuzhiyun {
1462*4882a593Smuzhiyun if (dcb->version >= 0x30)
1463*4882a593Smuzhiyun entry->tvconf.has_component_output = conf & (0x8 << 4);
1464*4882a593Smuzhiyun else
1465*4882a593Smuzhiyun entry->tvconf.has_component_output = false;
1466*4882a593Smuzhiyun
1467*4882a593Smuzhiyun break;
1468*4882a593Smuzhiyun }
1469*4882a593Smuzhiyun case DCB_OUTPUT_DP:
1470*4882a593Smuzhiyun entry->dpconf.sor.link = (conf & 0x00000030) >> 4;
1471*4882a593Smuzhiyun entry->extdev = (conf & 0x0000ff00) >> 8;
1472*4882a593Smuzhiyun switch ((conf & 0x00e00000) >> 21) {
1473*4882a593Smuzhiyun case 0:
1474*4882a593Smuzhiyun entry->dpconf.link_bw = 162000;
1475*4882a593Smuzhiyun break;
1476*4882a593Smuzhiyun case 1:
1477*4882a593Smuzhiyun entry->dpconf.link_bw = 270000;
1478*4882a593Smuzhiyun break;
1479*4882a593Smuzhiyun case 2:
1480*4882a593Smuzhiyun entry->dpconf.link_bw = 540000;
1481*4882a593Smuzhiyun break;
1482*4882a593Smuzhiyun case 3:
1483*4882a593Smuzhiyun default:
1484*4882a593Smuzhiyun entry->dpconf.link_bw = 810000;
1485*4882a593Smuzhiyun break;
1486*4882a593Smuzhiyun }
1487*4882a593Smuzhiyun switch ((conf & 0x0f000000) >> 24) {
1488*4882a593Smuzhiyun case 0xf:
1489*4882a593Smuzhiyun case 0x4:
1490*4882a593Smuzhiyun entry->dpconf.link_nr = 4;
1491*4882a593Smuzhiyun break;
1492*4882a593Smuzhiyun case 0x3:
1493*4882a593Smuzhiyun case 0x2:
1494*4882a593Smuzhiyun entry->dpconf.link_nr = 2;
1495*4882a593Smuzhiyun break;
1496*4882a593Smuzhiyun default:
1497*4882a593Smuzhiyun entry->dpconf.link_nr = 1;
1498*4882a593Smuzhiyun break;
1499*4882a593Smuzhiyun }
1500*4882a593Smuzhiyun link = entry->dpconf.sor.link;
1501*4882a593Smuzhiyun break;
1502*4882a593Smuzhiyun case DCB_OUTPUT_TMDS:
1503*4882a593Smuzhiyun if (dcb->version >= 0x40) {
1504*4882a593Smuzhiyun entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
1505*4882a593Smuzhiyun entry->extdev = (conf & 0x0000ff00) >> 8;
1506*4882a593Smuzhiyun link = entry->tmdsconf.sor.link;
1507*4882a593Smuzhiyun }
1508*4882a593Smuzhiyun else if (dcb->version >= 0x30)
1509*4882a593Smuzhiyun entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
1510*4882a593Smuzhiyun else if (dcb->version >= 0x22)
1511*4882a593Smuzhiyun entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;
1512*4882a593Smuzhiyun break;
1513*4882a593Smuzhiyun case DCB_OUTPUT_EOL:
1514*4882a593Smuzhiyun /* weird g80 mobile type that "nv" treats as a terminator */
1515*4882a593Smuzhiyun dcb->entries--;
1516*4882a593Smuzhiyun return false;
1517*4882a593Smuzhiyun default:
1518*4882a593Smuzhiyun break;
1519*4882a593Smuzhiyun }
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun if (dcb->version < 0x40) {
1522*4882a593Smuzhiyun /* Normal entries consist of a single bit, but dual link has
1523*4882a593Smuzhiyun * the next most significant bit set too
1524*4882a593Smuzhiyun */
1525*4882a593Smuzhiyun entry->duallink_possible =
1526*4882a593Smuzhiyun ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
1527*4882a593Smuzhiyun } else {
1528*4882a593Smuzhiyun entry->duallink_possible = (entry->sorconf.link == 3);
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun /* unsure what DCB version introduces this, 3.0? */
1532*4882a593Smuzhiyun if (conf & 0x100000)
1533*4882a593Smuzhiyun entry->i2c_upper_default = true;
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun entry->hasht = (entry->extdev << 8) | (entry->location << 4) |
1536*4882a593Smuzhiyun entry->type;
1537*4882a593Smuzhiyun entry->hashm = (entry->heads << 8) | (link << 6) | entry->or;
1538*4882a593Smuzhiyun return true;
1539*4882a593Smuzhiyun }
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun static bool
parse_dcb15_entry(struct drm_device * dev,struct dcb_table * dcb,uint32_t conn,uint32_t conf,struct dcb_output * entry)1542*4882a593Smuzhiyun parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb,
1543*4882a593Smuzhiyun uint32_t conn, uint32_t conf, struct dcb_output *entry)
1544*4882a593Smuzhiyun {
1545*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1546*4882a593Smuzhiyun
1547*4882a593Smuzhiyun switch (conn & 0x0000000f) {
1548*4882a593Smuzhiyun case 0:
1549*4882a593Smuzhiyun entry->type = DCB_OUTPUT_ANALOG;
1550*4882a593Smuzhiyun break;
1551*4882a593Smuzhiyun case 1:
1552*4882a593Smuzhiyun entry->type = DCB_OUTPUT_TV;
1553*4882a593Smuzhiyun break;
1554*4882a593Smuzhiyun case 2:
1555*4882a593Smuzhiyun case 4:
1556*4882a593Smuzhiyun if (conn & 0x10)
1557*4882a593Smuzhiyun entry->type = DCB_OUTPUT_LVDS;
1558*4882a593Smuzhiyun else
1559*4882a593Smuzhiyun entry->type = DCB_OUTPUT_TMDS;
1560*4882a593Smuzhiyun break;
1561*4882a593Smuzhiyun case 3:
1562*4882a593Smuzhiyun entry->type = DCB_OUTPUT_LVDS;
1563*4882a593Smuzhiyun break;
1564*4882a593Smuzhiyun default:
1565*4882a593Smuzhiyun NV_ERROR(drm, "Unknown DCB type %d\n", conn & 0x0000000f);
1566*4882a593Smuzhiyun return false;
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun
1569*4882a593Smuzhiyun entry->i2c_index = (conn & 0x0003c000) >> 14;
1570*4882a593Smuzhiyun entry->heads = ((conn & 0x001c0000) >> 18) + 1;
1571*4882a593Smuzhiyun entry->or = entry->heads; /* same as heads, hopefully safe enough */
1572*4882a593Smuzhiyun entry->location = (conn & 0x01e00000) >> 21;
1573*4882a593Smuzhiyun entry->bus = (conn & 0x0e000000) >> 25;
1574*4882a593Smuzhiyun entry->duallink_possible = false;
1575*4882a593Smuzhiyun
1576*4882a593Smuzhiyun switch (entry->type) {
1577*4882a593Smuzhiyun case DCB_OUTPUT_ANALOG:
1578*4882a593Smuzhiyun entry->crtconf.maxfreq = (conf & 0xffff) * 10;
1579*4882a593Smuzhiyun break;
1580*4882a593Smuzhiyun case DCB_OUTPUT_TV:
1581*4882a593Smuzhiyun entry->tvconf.has_component_output = false;
1582*4882a593Smuzhiyun break;
1583*4882a593Smuzhiyun case DCB_OUTPUT_LVDS:
1584*4882a593Smuzhiyun if ((conn & 0x00003f00) >> 8 != 0x10)
1585*4882a593Smuzhiyun entry->lvdsconf.use_straps_for_mode = true;
1586*4882a593Smuzhiyun entry->lvdsconf.use_power_scripts = true;
1587*4882a593Smuzhiyun break;
1588*4882a593Smuzhiyun default:
1589*4882a593Smuzhiyun break;
1590*4882a593Smuzhiyun }
1591*4882a593Smuzhiyun
1592*4882a593Smuzhiyun return true;
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun static
merge_like_dcb_entries(struct drm_device * dev,struct dcb_table * dcb)1596*4882a593Smuzhiyun void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
1597*4882a593Smuzhiyun {
1598*4882a593Smuzhiyun /*
1599*4882a593Smuzhiyun * DCB v2.0 lists each output combination separately.
1600*4882a593Smuzhiyun * Here we merge compatible entries to have fewer outputs, with
1601*4882a593Smuzhiyun * more options
1602*4882a593Smuzhiyun */
1603*4882a593Smuzhiyun
1604*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1605*4882a593Smuzhiyun int i, newentries = 0;
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun for (i = 0; i < dcb->entries; i++) {
1608*4882a593Smuzhiyun struct dcb_output *ient = &dcb->entry[i];
1609*4882a593Smuzhiyun int j;
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun for (j = i + 1; j < dcb->entries; j++) {
1612*4882a593Smuzhiyun struct dcb_output *jent = &dcb->entry[j];
1613*4882a593Smuzhiyun
1614*4882a593Smuzhiyun if (jent->type == 100) /* already merged entry */
1615*4882a593Smuzhiyun continue;
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun /* merge heads field when all other fields the same */
1618*4882a593Smuzhiyun if (jent->i2c_index == ient->i2c_index &&
1619*4882a593Smuzhiyun jent->type == ient->type &&
1620*4882a593Smuzhiyun jent->location == ient->location &&
1621*4882a593Smuzhiyun jent->or == ient->or) {
1622*4882a593Smuzhiyun NV_INFO(drm, "Merging DCB entries %d and %d\n",
1623*4882a593Smuzhiyun i, j);
1624*4882a593Smuzhiyun ient->heads |= jent->heads;
1625*4882a593Smuzhiyun jent->type = 100; /* dummy value */
1626*4882a593Smuzhiyun }
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun }
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun /* Compact entries merged into others out of dcb */
1631*4882a593Smuzhiyun for (i = 0; i < dcb->entries; i++) {
1632*4882a593Smuzhiyun if (dcb->entry[i].type == 100)
1633*4882a593Smuzhiyun continue;
1634*4882a593Smuzhiyun
1635*4882a593Smuzhiyun if (newentries != i) {
1636*4882a593Smuzhiyun dcb->entry[newentries] = dcb->entry[i];
1637*4882a593Smuzhiyun dcb->entry[newentries].index = newentries;
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun newentries++;
1640*4882a593Smuzhiyun }
1641*4882a593Smuzhiyun
1642*4882a593Smuzhiyun dcb->entries = newentries;
1643*4882a593Smuzhiyun }
1644*4882a593Smuzhiyun
1645*4882a593Smuzhiyun static bool
apply_dcb_encoder_quirks(struct drm_device * dev,int idx,u32 * conn,u32 * conf)1646*4882a593Smuzhiyun apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
1647*4882a593Smuzhiyun {
1648*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1649*4882a593Smuzhiyun struct dcb_table *dcb = &drm->vbios.dcb;
1650*4882a593Smuzhiyun
1651*4882a593Smuzhiyun /* Dell Precision M6300
1652*4882a593Smuzhiyun * DCB entry 2: 02025312 00000010
1653*4882a593Smuzhiyun * DCB entry 3: 02026312 00000020
1654*4882a593Smuzhiyun *
1655*4882a593Smuzhiyun * Identical, except apparently a different connector on a
1656*4882a593Smuzhiyun * different SOR link. Not a clue how we're supposed to know
1657*4882a593Smuzhiyun * which one is in use if it even shares an i2c line...
1658*4882a593Smuzhiyun *
1659*4882a593Smuzhiyun * Ignore the connector on the second SOR link to prevent
1660*4882a593Smuzhiyun * nasty problems until this is sorted (assuming it's not a
1661*4882a593Smuzhiyun * VBIOS bug).
1662*4882a593Smuzhiyun */
1663*4882a593Smuzhiyun if (nv_match_device(dev, 0x040d, 0x1028, 0x019b)) {
1664*4882a593Smuzhiyun if (*conn == 0x02026312 && *conf == 0x00000020)
1665*4882a593Smuzhiyun return false;
1666*4882a593Smuzhiyun }
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun /* GeForce3 Ti 200
1669*4882a593Smuzhiyun *
1670*4882a593Smuzhiyun * DCB reports an LVDS output that should be TMDS:
1671*4882a593Smuzhiyun * DCB entry 1: f2005014 ffffffff
1672*4882a593Smuzhiyun */
1673*4882a593Smuzhiyun if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
1674*4882a593Smuzhiyun if (*conn == 0xf2005014 && *conf == 0xffffffff) {
1675*4882a593Smuzhiyun fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
1676*4882a593Smuzhiyun return false;
1677*4882a593Smuzhiyun }
1678*4882a593Smuzhiyun }
1679*4882a593Smuzhiyun
1680*4882a593Smuzhiyun /* XFX GT-240X-YA
1681*4882a593Smuzhiyun *
1682*4882a593Smuzhiyun * So many things wrong here, replace the entire encoder table..
1683*4882a593Smuzhiyun */
1684*4882a593Smuzhiyun if (nv_match_device(dev, 0x0ca3, 0x1682, 0x3003)) {
1685*4882a593Smuzhiyun if (idx == 0) {
1686*4882a593Smuzhiyun *conn = 0x02001300; /* VGA, connector 1 */
1687*4882a593Smuzhiyun *conf = 0x00000028;
1688*4882a593Smuzhiyun } else
1689*4882a593Smuzhiyun if (idx == 1) {
1690*4882a593Smuzhiyun *conn = 0x01010312; /* DVI, connector 0 */
1691*4882a593Smuzhiyun *conf = 0x00020030;
1692*4882a593Smuzhiyun } else
1693*4882a593Smuzhiyun if (idx == 2) {
1694*4882a593Smuzhiyun *conn = 0x01010310; /* VGA, connector 0 */
1695*4882a593Smuzhiyun *conf = 0x00000028;
1696*4882a593Smuzhiyun } else
1697*4882a593Smuzhiyun if (idx == 3) {
1698*4882a593Smuzhiyun *conn = 0x02022362; /* HDMI, connector 2 */
1699*4882a593Smuzhiyun *conf = 0x00020010;
1700*4882a593Smuzhiyun } else {
1701*4882a593Smuzhiyun *conn = 0x0000000e; /* EOL */
1702*4882a593Smuzhiyun *conf = 0x00000000;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun }
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun /* Some other twisted XFX board (rhbz#694914)
1707*4882a593Smuzhiyun *
1708*4882a593Smuzhiyun * The DVI/VGA encoder combo that's supposed to represent the
1709*4882a593Smuzhiyun * DVI-I connector actually point at two different ones, and
1710*4882a593Smuzhiyun * the HDMI connector ends up paired with the VGA instead.
1711*4882a593Smuzhiyun *
1712*4882a593Smuzhiyun * Connector table is missing anything for VGA at all, pointing it
1713*4882a593Smuzhiyun * an invalid conntab entry 2 so we figure it out ourself.
1714*4882a593Smuzhiyun */
1715*4882a593Smuzhiyun if (nv_match_device(dev, 0x0615, 0x1682, 0x2605)) {
1716*4882a593Smuzhiyun if (idx == 0) {
1717*4882a593Smuzhiyun *conn = 0x02002300; /* VGA, connector 2 */
1718*4882a593Smuzhiyun *conf = 0x00000028;
1719*4882a593Smuzhiyun } else
1720*4882a593Smuzhiyun if (idx == 1) {
1721*4882a593Smuzhiyun *conn = 0x01010312; /* DVI, connector 0 */
1722*4882a593Smuzhiyun *conf = 0x00020030;
1723*4882a593Smuzhiyun } else
1724*4882a593Smuzhiyun if (idx == 2) {
1725*4882a593Smuzhiyun *conn = 0x04020310; /* VGA, connector 0 */
1726*4882a593Smuzhiyun *conf = 0x00000028;
1727*4882a593Smuzhiyun } else
1728*4882a593Smuzhiyun if (idx == 3) {
1729*4882a593Smuzhiyun *conn = 0x02021322; /* HDMI, connector 1 */
1730*4882a593Smuzhiyun *conf = 0x00020010;
1731*4882a593Smuzhiyun } else {
1732*4882a593Smuzhiyun *conn = 0x0000000e; /* EOL */
1733*4882a593Smuzhiyun *conf = 0x00000000;
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun }
1736*4882a593Smuzhiyun
1737*4882a593Smuzhiyun /* fdo#50830: connector indices for VGA and DVI-I are backwards */
1738*4882a593Smuzhiyun if (nv_match_device(dev, 0x0421, 0x3842, 0xc793)) {
1739*4882a593Smuzhiyun if (idx == 0 && *conn == 0x02000300)
1740*4882a593Smuzhiyun *conn = 0x02011300;
1741*4882a593Smuzhiyun else
1742*4882a593Smuzhiyun if (idx == 1 && *conn == 0x04011310)
1743*4882a593Smuzhiyun *conn = 0x04000310;
1744*4882a593Smuzhiyun else
1745*4882a593Smuzhiyun if (idx == 2 && *conn == 0x02011312)
1746*4882a593Smuzhiyun *conn = 0x02000312;
1747*4882a593Smuzhiyun }
1748*4882a593Smuzhiyun
1749*4882a593Smuzhiyun return true;
1750*4882a593Smuzhiyun }
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun static void
fabricate_dcb_encoder_table(struct drm_device * dev,struct nvbios * bios)1753*4882a593Smuzhiyun fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
1754*4882a593Smuzhiyun {
1755*4882a593Smuzhiyun struct dcb_table *dcb = &bios->dcb;
1756*4882a593Smuzhiyun int all_heads = (nv_two_heads(dev) ? 3 : 1);
1757*4882a593Smuzhiyun
1758*4882a593Smuzhiyun #ifdef __powerpc__
1759*4882a593Smuzhiyun /* Apple iMac G4 NV17 */
1760*4882a593Smuzhiyun if (of_machine_is_compatible("PowerMac4,5")) {
1761*4882a593Smuzhiyun fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
1762*4882a593Smuzhiyun fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
1763*4882a593Smuzhiyun return;
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun #endif
1766*4882a593Smuzhiyun
1767*4882a593Smuzhiyun /* Make up some sane defaults */
1768*4882a593Smuzhiyun fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
1769*4882a593Smuzhiyun bios->legacy.i2c_indices.crt, 1, 1);
1770*4882a593Smuzhiyun
1771*4882a593Smuzhiyun if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
1772*4882a593Smuzhiyun fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
1773*4882a593Smuzhiyun bios->legacy.i2c_indices.tv,
1774*4882a593Smuzhiyun all_heads, 0);
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun else if (bios->tmds.output0_script_ptr ||
1777*4882a593Smuzhiyun bios->tmds.output1_script_ptr)
1778*4882a593Smuzhiyun fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
1779*4882a593Smuzhiyun bios->legacy.i2c_indices.panel,
1780*4882a593Smuzhiyun all_heads, 1);
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun
1783*4882a593Smuzhiyun static int
parse_dcb_entry(struct drm_device * dev,void * data,int idx,u8 * outp)1784*4882a593Smuzhiyun parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp)
1785*4882a593Smuzhiyun {
1786*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1787*4882a593Smuzhiyun struct dcb_table *dcb = &drm->vbios.dcb;
1788*4882a593Smuzhiyun u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]);
1789*4882a593Smuzhiyun u32 conn = ROM32(outp[0]);
1790*4882a593Smuzhiyun bool ret;
1791*4882a593Smuzhiyun
1792*4882a593Smuzhiyun if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) {
1793*4882a593Smuzhiyun struct dcb_output *entry = new_dcb_entry(dcb);
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun NV_INFO(drm, "DCB outp %02d: %08x %08x\n", idx, conn, conf);
1796*4882a593Smuzhiyun
1797*4882a593Smuzhiyun if (dcb->version >= 0x20)
1798*4882a593Smuzhiyun ret = parse_dcb20_entry(dev, dcb, conn, conf, entry);
1799*4882a593Smuzhiyun else
1800*4882a593Smuzhiyun ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
1801*4882a593Smuzhiyun if (!ret)
1802*4882a593Smuzhiyun return 1; /* stop parsing */
1803*4882a593Smuzhiyun
1804*4882a593Smuzhiyun /* Ignore the I2C index for on-chip TV-out, as there
1805*4882a593Smuzhiyun * are cards with bogus values (nv31m in bug 23212),
1806*4882a593Smuzhiyun * and it's otherwise useless.
1807*4882a593Smuzhiyun */
1808*4882a593Smuzhiyun if (entry->type == DCB_OUTPUT_TV &&
1809*4882a593Smuzhiyun entry->location == DCB_LOC_ON_CHIP)
1810*4882a593Smuzhiyun entry->i2c_index = 0x0f;
1811*4882a593Smuzhiyun }
1812*4882a593Smuzhiyun
1813*4882a593Smuzhiyun return 0;
1814*4882a593Smuzhiyun }
1815*4882a593Smuzhiyun
1816*4882a593Smuzhiyun static void
dcb_fake_connectors(struct nvbios * bios)1817*4882a593Smuzhiyun dcb_fake_connectors(struct nvbios *bios)
1818*4882a593Smuzhiyun {
1819*4882a593Smuzhiyun struct dcb_table *dcbt = &bios->dcb;
1820*4882a593Smuzhiyun u8 map[16] = { };
1821*4882a593Smuzhiyun int i, idx = 0;
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun /* heuristic: if we ever get a non-zero connector field, assume
1824*4882a593Smuzhiyun * that all the indices are valid and we don't need fake them.
1825*4882a593Smuzhiyun *
1826*4882a593Smuzhiyun * and, as usual, a blacklist of boards with bad bios data..
1827*4882a593Smuzhiyun */
1828*4882a593Smuzhiyun if (!nv_match_device(bios->dev, 0x0392, 0x107d, 0x20a2)) {
1829*4882a593Smuzhiyun for (i = 0; i < dcbt->entries; i++) {
1830*4882a593Smuzhiyun if (dcbt->entry[i].connector)
1831*4882a593Smuzhiyun return;
1832*4882a593Smuzhiyun }
1833*4882a593Smuzhiyun }
1834*4882a593Smuzhiyun
1835*4882a593Smuzhiyun /* no useful connector info available, we need to make it up
1836*4882a593Smuzhiyun * ourselves. the rule here is: anything on the same i2c bus
1837*4882a593Smuzhiyun * is considered to be on the same connector. any output
1838*4882a593Smuzhiyun * without an associated i2c bus is assigned its own unique
1839*4882a593Smuzhiyun * connector index.
1840*4882a593Smuzhiyun */
1841*4882a593Smuzhiyun for (i = 0; i < dcbt->entries; i++) {
1842*4882a593Smuzhiyun u8 i2c = dcbt->entry[i].i2c_index;
1843*4882a593Smuzhiyun if (i2c == 0x0f) {
1844*4882a593Smuzhiyun dcbt->entry[i].connector = idx++;
1845*4882a593Smuzhiyun } else {
1846*4882a593Smuzhiyun if (!map[i2c])
1847*4882a593Smuzhiyun map[i2c] = ++idx;
1848*4882a593Smuzhiyun dcbt->entry[i].connector = map[i2c] - 1;
1849*4882a593Smuzhiyun }
1850*4882a593Smuzhiyun }
1851*4882a593Smuzhiyun
1852*4882a593Smuzhiyun /* if we created more than one connector, destroy the connector
1853*4882a593Smuzhiyun * table - just in case it has random, rather than stub, entries.
1854*4882a593Smuzhiyun */
1855*4882a593Smuzhiyun if (i > 1) {
1856*4882a593Smuzhiyun u8 *conntab = olddcb_conntab(bios->dev);
1857*4882a593Smuzhiyun if (conntab)
1858*4882a593Smuzhiyun conntab[0] = 0x00;
1859*4882a593Smuzhiyun }
1860*4882a593Smuzhiyun }
1861*4882a593Smuzhiyun
1862*4882a593Smuzhiyun static int
parse_dcb_table(struct drm_device * dev,struct nvbios * bios)1863*4882a593Smuzhiyun parse_dcb_table(struct drm_device *dev, struct nvbios *bios)
1864*4882a593Smuzhiyun {
1865*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1866*4882a593Smuzhiyun struct dcb_table *dcb = &bios->dcb;
1867*4882a593Smuzhiyun u8 *dcbt, *conn;
1868*4882a593Smuzhiyun int idx;
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun dcbt = olddcb_table(dev);
1871*4882a593Smuzhiyun if (!dcbt) {
1872*4882a593Smuzhiyun /* handle pre-DCB boards */
1873*4882a593Smuzhiyun if (bios->type == NVBIOS_BMP) {
1874*4882a593Smuzhiyun fabricate_dcb_encoder_table(dev, bios);
1875*4882a593Smuzhiyun return 0;
1876*4882a593Smuzhiyun }
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun return -EINVAL;
1879*4882a593Smuzhiyun }
1880*4882a593Smuzhiyun
1881*4882a593Smuzhiyun NV_INFO(drm, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf);
1882*4882a593Smuzhiyun
1883*4882a593Smuzhiyun dcb->version = dcbt[0];
1884*4882a593Smuzhiyun olddcb_outp_foreach(dev, NULL, parse_dcb_entry);
1885*4882a593Smuzhiyun
1886*4882a593Smuzhiyun /*
1887*4882a593Smuzhiyun * apart for v2.1+ not being known for requiring merging, this
1888*4882a593Smuzhiyun * guarantees dcbent->index is the index of the entry in the rom image
1889*4882a593Smuzhiyun */
1890*4882a593Smuzhiyun if (dcb->version < 0x21)
1891*4882a593Smuzhiyun merge_like_dcb_entries(dev, dcb);
1892*4882a593Smuzhiyun
1893*4882a593Smuzhiyun /* dump connector table entries to log, if any exist */
1894*4882a593Smuzhiyun idx = -1;
1895*4882a593Smuzhiyun while ((conn = olddcb_conn(dev, ++idx))) {
1896*4882a593Smuzhiyun if (conn[0] != 0xff) {
1897*4882a593Smuzhiyun if (olddcb_conntab(dev)[3] < 4)
1898*4882a593Smuzhiyun NV_INFO(drm, "DCB conn %02d: %04x\n",
1899*4882a593Smuzhiyun idx, ROM16(conn[0]));
1900*4882a593Smuzhiyun else
1901*4882a593Smuzhiyun NV_INFO(drm, "DCB conn %02d: %08x\n",
1902*4882a593Smuzhiyun idx, ROM32(conn[0]));
1903*4882a593Smuzhiyun }
1904*4882a593Smuzhiyun }
1905*4882a593Smuzhiyun dcb_fake_connectors(bios);
1906*4882a593Smuzhiyun return 0;
1907*4882a593Smuzhiyun }
1908*4882a593Smuzhiyun
load_nv17_hwsq_ucode_entry(struct drm_device * dev,struct nvbios * bios,uint16_t hwsq_offset,int entry)1909*4882a593Smuzhiyun static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry)
1910*4882a593Smuzhiyun {
1911*4882a593Smuzhiyun /*
1912*4882a593Smuzhiyun * The header following the "HWSQ" signature has the number of entries,
1913*4882a593Smuzhiyun * and the entry size
1914*4882a593Smuzhiyun *
1915*4882a593Smuzhiyun * An entry consists of a dword to write to the sequencer control reg
1916*4882a593Smuzhiyun * (0x00001304), followed by the ucode bytes, written sequentially,
1917*4882a593Smuzhiyun * starting at reg 0x00001400
1918*4882a593Smuzhiyun */
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1921*4882a593Smuzhiyun struct nvif_object *device = &drm->client.device.object;
1922*4882a593Smuzhiyun uint8_t bytes_to_write;
1923*4882a593Smuzhiyun uint16_t hwsq_entry_offset;
1924*4882a593Smuzhiyun int i;
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun if (bios->data[hwsq_offset] <= entry) {
1927*4882a593Smuzhiyun NV_ERROR(drm, "Too few entries in HW sequencer table for "
1928*4882a593Smuzhiyun "requested entry\n");
1929*4882a593Smuzhiyun return -ENOENT;
1930*4882a593Smuzhiyun }
1931*4882a593Smuzhiyun
1932*4882a593Smuzhiyun bytes_to_write = bios->data[hwsq_offset + 1];
1933*4882a593Smuzhiyun
1934*4882a593Smuzhiyun if (bytes_to_write != 36) {
1935*4882a593Smuzhiyun NV_ERROR(drm, "Unknown HW sequencer entry size\n");
1936*4882a593Smuzhiyun return -EINVAL;
1937*4882a593Smuzhiyun }
1938*4882a593Smuzhiyun
1939*4882a593Smuzhiyun NV_INFO(drm, "Loading NV17 power sequencing microcode\n");
1940*4882a593Smuzhiyun
1941*4882a593Smuzhiyun hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write;
1942*4882a593Smuzhiyun
1943*4882a593Smuzhiyun /* set sequencer control */
1944*4882a593Smuzhiyun nvif_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
1945*4882a593Smuzhiyun bytes_to_write -= 4;
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun /* write ucode */
1948*4882a593Smuzhiyun for (i = 0; i < bytes_to_write; i += 4)
1949*4882a593Smuzhiyun nvif_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
1950*4882a593Smuzhiyun
1951*4882a593Smuzhiyun /* twiddle NV_PBUS_DEBUG_4 */
1952*4882a593Smuzhiyun nvif_wr32(device, NV_PBUS_DEBUG_4, nvif_rd32(device, NV_PBUS_DEBUG_4) | 0x18);
1953*4882a593Smuzhiyun
1954*4882a593Smuzhiyun return 0;
1955*4882a593Smuzhiyun }
1956*4882a593Smuzhiyun
load_nv17_hw_sequencer_ucode(struct drm_device * dev,struct nvbios * bios)1957*4882a593Smuzhiyun static int load_nv17_hw_sequencer_ucode(struct drm_device *dev,
1958*4882a593Smuzhiyun struct nvbios *bios)
1959*4882a593Smuzhiyun {
1960*4882a593Smuzhiyun /*
1961*4882a593Smuzhiyun * BMP based cards, from NV17, need a microcode loading to correctly
1962*4882a593Smuzhiyun * control the GPIO etc for LVDS panels
1963*4882a593Smuzhiyun *
1964*4882a593Smuzhiyun * BIT based cards seem to do this directly in the init scripts
1965*4882a593Smuzhiyun *
1966*4882a593Smuzhiyun * The microcode entries are found by the "HWSQ" signature.
1967*4882a593Smuzhiyun */
1968*4882a593Smuzhiyun
1969*4882a593Smuzhiyun static const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' };
1970*4882a593Smuzhiyun const int sz = sizeof(hwsq_signature);
1971*4882a593Smuzhiyun int hwsq_offset;
1972*4882a593Smuzhiyun
1973*4882a593Smuzhiyun hwsq_offset = findstr(bios->data, bios->length, hwsq_signature, sz);
1974*4882a593Smuzhiyun if (!hwsq_offset)
1975*4882a593Smuzhiyun return 0;
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun /* always use entry 0? */
1978*4882a593Smuzhiyun return load_nv17_hwsq_ucode_entry(dev, bios, hwsq_offset + sz, 0);
1979*4882a593Smuzhiyun }
1980*4882a593Smuzhiyun
nouveau_bios_embedded_edid(struct drm_device * dev)1981*4882a593Smuzhiyun uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
1982*4882a593Smuzhiyun {
1983*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
1984*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
1985*4882a593Smuzhiyun static const uint8_t edid_sig[] = {
1986*4882a593Smuzhiyun 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
1987*4882a593Smuzhiyun uint16_t offset = 0;
1988*4882a593Smuzhiyun uint16_t newoffset;
1989*4882a593Smuzhiyun int searchlen = NV_PROM_SIZE;
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun if (bios->fp.edid)
1992*4882a593Smuzhiyun return bios->fp.edid;
1993*4882a593Smuzhiyun
1994*4882a593Smuzhiyun while (searchlen) {
1995*4882a593Smuzhiyun newoffset = findstr(&bios->data[offset], searchlen,
1996*4882a593Smuzhiyun edid_sig, 8);
1997*4882a593Smuzhiyun if (!newoffset)
1998*4882a593Smuzhiyun return NULL;
1999*4882a593Smuzhiyun offset += newoffset;
2000*4882a593Smuzhiyun if (!nv_cksum(&bios->data[offset], EDID1_LEN))
2001*4882a593Smuzhiyun break;
2002*4882a593Smuzhiyun
2003*4882a593Smuzhiyun searchlen -= offset;
2004*4882a593Smuzhiyun offset++;
2005*4882a593Smuzhiyun }
2006*4882a593Smuzhiyun
2007*4882a593Smuzhiyun NV_INFO(drm, "Found EDID in BIOS\n");
2008*4882a593Smuzhiyun
2009*4882a593Smuzhiyun return bios->fp.edid = &bios->data[offset];
2010*4882a593Smuzhiyun }
2011*4882a593Smuzhiyun
NVInitVBIOS(struct drm_device * dev)2012*4882a593Smuzhiyun static bool NVInitVBIOS(struct drm_device *dev)
2013*4882a593Smuzhiyun {
2014*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
2015*4882a593Smuzhiyun struct nvkm_bios *bios = nvxx_bios(&drm->client.device);
2016*4882a593Smuzhiyun struct nvbios *legacy = &drm->vbios;
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun memset(legacy, 0, sizeof(struct nvbios));
2019*4882a593Smuzhiyun spin_lock_init(&legacy->lock);
2020*4882a593Smuzhiyun legacy->dev = dev;
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun legacy->data = bios->data;
2023*4882a593Smuzhiyun legacy->length = bios->size;
2024*4882a593Smuzhiyun legacy->major_version = bios->version.major;
2025*4882a593Smuzhiyun legacy->chip_version = bios->version.chip;
2026*4882a593Smuzhiyun if (bios->bit_offset) {
2027*4882a593Smuzhiyun legacy->type = NVBIOS_BIT;
2028*4882a593Smuzhiyun legacy->offset = bios->bit_offset;
2029*4882a593Smuzhiyun return !parse_bit_structure(legacy, legacy->offset + 6);
2030*4882a593Smuzhiyun } else
2031*4882a593Smuzhiyun if (bios->bmp_offset) {
2032*4882a593Smuzhiyun legacy->type = NVBIOS_BMP;
2033*4882a593Smuzhiyun legacy->offset = bios->bmp_offset;
2034*4882a593Smuzhiyun return !parse_bmp_structure(dev, legacy, legacy->offset);
2035*4882a593Smuzhiyun }
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun return false;
2038*4882a593Smuzhiyun }
2039*4882a593Smuzhiyun
2040*4882a593Smuzhiyun int
nouveau_run_vbios_init(struct drm_device * dev)2041*4882a593Smuzhiyun nouveau_run_vbios_init(struct drm_device *dev)
2042*4882a593Smuzhiyun {
2043*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
2044*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
2045*4882a593Smuzhiyun int ret = 0;
2046*4882a593Smuzhiyun
2047*4882a593Smuzhiyun /* Reset the BIOS head to 0. */
2048*4882a593Smuzhiyun bios->state.crtchead = 0;
2049*4882a593Smuzhiyun
2050*4882a593Smuzhiyun if (bios->major_version < 5) /* BMP only */
2051*4882a593Smuzhiyun load_nv17_hw_sequencer_ucode(dev, bios);
2052*4882a593Smuzhiyun
2053*4882a593Smuzhiyun if (bios->execute) {
2054*4882a593Smuzhiyun bios->fp.last_script_invoc = 0;
2055*4882a593Smuzhiyun bios->fp.lvds_init_run = false;
2056*4882a593Smuzhiyun }
2057*4882a593Smuzhiyun
2058*4882a593Smuzhiyun return ret;
2059*4882a593Smuzhiyun }
2060*4882a593Smuzhiyun
2061*4882a593Smuzhiyun static bool
nouveau_bios_posted(struct drm_device * dev)2062*4882a593Smuzhiyun nouveau_bios_posted(struct drm_device *dev)
2063*4882a593Smuzhiyun {
2064*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
2065*4882a593Smuzhiyun unsigned htotal;
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA)
2068*4882a593Smuzhiyun return true;
2069*4882a593Smuzhiyun
2070*4882a593Smuzhiyun htotal = NVReadVgaCrtc(dev, 0, 0x06);
2071*4882a593Smuzhiyun htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8;
2072*4882a593Smuzhiyun htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4;
2073*4882a593Smuzhiyun htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10;
2074*4882a593Smuzhiyun htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11;
2075*4882a593Smuzhiyun return (htotal != 0);
2076*4882a593Smuzhiyun }
2077*4882a593Smuzhiyun
2078*4882a593Smuzhiyun int
nouveau_bios_init(struct drm_device * dev)2079*4882a593Smuzhiyun nouveau_bios_init(struct drm_device *dev)
2080*4882a593Smuzhiyun {
2081*4882a593Smuzhiyun struct nouveau_drm *drm = nouveau_drm(dev);
2082*4882a593Smuzhiyun struct nvbios *bios = &drm->vbios;
2083*4882a593Smuzhiyun int ret;
2084*4882a593Smuzhiyun
2085*4882a593Smuzhiyun /* only relevant for PCI devices */
2086*4882a593Smuzhiyun if (!dev->pdev)
2087*4882a593Smuzhiyun return 0;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun if (!NVInitVBIOS(dev))
2090*4882a593Smuzhiyun return -ENODEV;
2091*4882a593Smuzhiyun
2092*4882a593Smuzhiyun ret = parse_dcb_table(dev, bios);
2093*4882a593Smuzhiyun if (ret)
2094*4882a593Smuzhiyun return ret;
2095*4882a593Smuzhiyun
2096*4882a593Smuzhiyun if (!bios->major_version) /* we don't run version 0 bios */
2097*4882a593Smuzhiyun return 0;
2098*4882a593Smuzhiyun
2099*4882a593Smuzhiyun /* init script execution disabled */
2100*4882a593Smuzhiyun bios->execute = false;
2101*4882a593Smuzhiyun
2102*4882a593Smuzhiyun /* ... unless card isn't POSTed already */
2103*4882a593Smuzhiyun if (!nouveau_bios_posted(dev)) {
2104*4882a593Smuzhiyun NV_INFO(drm, "Adaptor not initialised, "
2105*4882a593Smuzhiyun "running VBIOS init tables.\n");
2106*4882a593Smuzhiyun bios->execute = true;
2107*4882a593Smuzhiyun }
2108*4882a593Smuzhiyun
2109*4882a593Smuzhiyun ret = nouveau_run_vbios_init(dev);
2110*4882a593Smuzhiyun if (ret)
2111*4882a593Smuzhiyun return ret;
2112*4882a593Smuzhiyun
2113*4882a593Smuzhiyun /* feature_byte on BMP is poor, but init always sets CR4B */
2114*4882a593Smuzhiyun if (bios->major_version < 5)
2115*4882a593Smuzhiyun bios->is_mobile = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_4B) & 0x40;
2116*4882a593Smuzhiyun
2117*4882a593Smuzhiyun /* all BIT systems need p_f_m_t for digital_min_front_porch */
2118*4882a593Smuzhiyun if (bios->is_mobile || bios->major_version >= 5)
2119*4882a593Smuzhiyun ret = parse_fp_mode_table(dev, bios);
2120*4882a593Smuzhiyun
2121*4882a593Smuzhiyun /* allow subsequent scripts to execute */
2122*4882a593Smuzhiyun bios->execute = true;
2123*4882a593Smuzhiyun
2124*4882a593Smuzhiyun return 0;
2125*4882a593Smuzhiyun }
2126*4882a593Smuzhiyun
2127*4882a593Smuzhiyun void
nouveau_bios_takedown(struct drm_device * dev)2128*4882a593Smuzhiyun nouveau_bios_takedown(struct drm_device *dev)
2129*4882a593Smuzhiyun {
2130*4882a593Smuzhiyun }
2131