Loading drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c +33 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ * Authors: Ben Skeggs */ #include <subdev/bios.h> #include <subdev/bios/dcb.h> #include <subdev/bios/disp.h> #include <subdev/bios/init.h> #include <subdev/devinit.h> #include <subdev/vga.h> Loading Loading @@ -55,7 +59,12 @@ nv50_devinit_dtor(struct nouveau_object *object) static int nv50_devinit_init(struct nouveau_object *object) { struct nouveau_bios *bios = nouveau_bios(object); struct nv50_devinit_priv *priv = (void *)object; struct nvbios_outp info; struct dcb_output outp; u8 ver = 0xff, hdr, cnt, len; int ret, i = 0; if (!priv->base.post) { if (!nv_rdvgac(priv, 0, 0x00) && Loading @@ -65,7 +74,30 @@ nv50_devinit_init(struct nouveau_object *object) } } return nouveau_devinit_init(&priv->base); ret = nouveau_devinit_init(&priv->base); if (ret) return ret; /* if we ran the init tables, execute first script pointer for each * display table output entry that has a matching dcb entry. */ while (priv->base.post && ver) { u16 data = nvbios_outp_parse(bios, i++, &ver, &hdr, &cnt, &len, &info); if (data && dcb_outp_match(bios, info.type, info.mask, &ver, &len, &outp)) { struct nvbios_init init = { .subdev = nv_subdev(priv), .bios = bios, .offset = info.script[0], .outp = &outp, .crtc = -1, .execute = 1, }; nvbios_exec(&init); } }; return 0; } static int Loading drivers/gpu/drm/nouveau/nouveau_bios.c +1 −206 Original line number Diff line number Diff line Loading @@ -652,178 +652,6 @@ bios_encoder_match(struct dcb_output *dcb, u32 hash) } } int nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, struct dcb_output *dcbent, int crtc) { /* * The display script table is located by the BIT 'U' table. * * It contains an array of pointers to various tables describing * a particular output type. The first 32-bits of the output * tables contains similar information to a DCB entry, and is * used to decide whether that particular table is suitable for * the output you want to access. * * The "record header length" field here seems to indicate the * offset of the first configuration entry in the output tables. * This is 10 on most cards I've seen, but 12 has been witnessed * on DP cards, and there's another script pointer within the * header. * * offset + 0 ( 8 bits): version * offset + 1 ( 8 bits): header length * offset + 2 ( 8 bits): record length * offset + 3 ( 8 bits): number of records * offset + 4 ( 8 bits): record header length * offset + 5 (16 bits): pointer to first output script table */ struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; uint8_t *table = &bios->data[bios->display.script_table_ptr]; uint8_t *otable = NULL; uint16_t script; int i; if (!bios->display.script_table_ptr) { NV_ERROR(drm, "No pointer to output script table\n"); return 1; } /* * Nothing useful has been in any of the pre-2.0 tables I've seen, * so until they are, we really don't need to care. */ if (table[0] < 0x20) return 1; if (table[0] != 0x20 && table[0] != 0x21) { NV_ERROR(drm, "Output script table version 0x%02x unknown\n", table[0]); return 1; } /* * The output script tables describing a particular output type * look as follows: * * offset + 0 (32 bits): output this table matches (hash of DCB) * offset + 4 ( 8 bits): unknown * offset + 5 ( 8 bits): number of configurations * offset + 6 (16 bits): pointer to some script * offset + 8 (16 bits): pointer to some script * * headerlen == 10 * offset + 10 : configuration 0 * * headerlen == 12 * offset + 10 : pointer to some script * offset + 12 : configuration 0 * * Each config entry is as follows: * * offset + 0 (16 bits): unknown, assumed to be a match value * offset + 2 (16 bits): pointer to script table (clock set?) * offset + 4 (16 bits): pointer to script table (reset?) * * There doesn't appear to be a count value to say how many * entries exist in each script table, instead, a 0 value in * the first 16-bit word seems to indicate both the end of the * list and the default entry. The second 16-bit word in the * script tables is a pointer to the script to execute. */ NV_DEBUG(drm, "Searching for output entry for %d %d %d\n", dcbent->type, dcbent->location, dcbent->or); for (i = 0; i < table[3]; i++) { otable = ROMPTR(dev, table[table[1] + (i * table[2])]); if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) break; } if (!otable) { NV_DEBUG(drm, "failed to match any output table\n"); return 1; } if (pclk < -2 || pclk > 0) { /* Try to find matching script table entry */ for (i = 0; i < otable[5]; i++) { if (ROM16(otable[table[4] + i*6]) == type) break; } if (i == otable[5]) { NV_ERROR(drm, "Table 0x%04x not found for %d/%d, " "using first\n", type, dcbent->type, dcbent->or); i = 0; } } if (pclk == 0) { script = ROM16(otable[6]); if (!script) { NV_DEBUG(drm, "output script 0 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing output script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk == -1) { script = ROM16(otable[8]); if (!script) { NV_DEBUG(drm, "output script 1 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing output script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk == -2) { if (table[4] >= 12) script = ROM16(otable[10]); else script = 0; if (!script) { NV_DEBUG(drm, "output script 2 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing output script 2\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk > 0) { script = ROM16(otable[table[4] + i*6 + 2]); if (script) script = clkcmptable(bios, script, pclk); if (!script) { NV_DEBUG(drm, "clock script 0 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing clock script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk < 0) { script = ROM16(otable[table[4] + i*6 + 4]); if (script) script = clkcmptable(bios, script, -pclk); if (!script) { NV_DEBUG(drm, "clock script 1 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing clock script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } return 0; } int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk) { /* Loading Loading @@ -1212,31 +1040,6 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, return 0; } static int parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) { /* * Parses the pointer to the G80 output script tables * * Starting at bitentry->offset: * * offset + 0 (16 bits): output script table pointer */ struct nouveau_drm *drm = nouveau_drm(dev); uint16_t outputscripttableptr; if (bitentry->length != 3) { NV_ERROR(drm, "Do not understand BIT U table\n"); return -EINVAL; } outputscripttableptr = ROM16(bios->data[bitentry->offset]); bios->display.script_table_ptr = outputscripttableptr; return 0; } struct bit_table { const char id; int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); Loading Loading @@ -1313,7 +1116,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) parse_bit_table(bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */ parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); return 0; } Loading Loading @@ -2324,7 +2126,7 @@ nouveau_run_vbios_init(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; int i, ret = 0; int ret = 0; /* Reset the BIOS head to 0. */ bios->state.crtchead = 0; Loading @@ -2337,13 +2139,6 @@ nouveau_run_vbios_init(struct drm_device *dev) bios->fp.lvds_init_run = false; } if (nv_device(drm->device)->card_type >= NV_50) { for (i = 0; bios->execute && i < bios->dcb.entries; i++) { nouveau_bios_run_display_table(dev, 0, 0, &bios->dcb.entry[i], -1); } } return ret; } Loading drivers/gpu/drm/nouveau/nouveau_bios.h +0 −8 Original line number Diff line number Diff line Loading @@ -127,12 +127,6 @@ struct nvbios { int crtchead; } state; struct { struct dcb_output *output; int crtc; uint16_t script_table_ptr; } display; struct { uint16_t fptablepointer; /* also used by tmds */ uint16_t fpxlatetableptr; Loading Loading @@ -185,8 +179,6 @@ void nouveau_bios_takedown(struct drm_device *dev); int nouveau_run_vbios_init(struct drm_device *); struct dcb_connector_table_entry * nouveau_bios_connector_entry(struct drm_device *, int index); int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, struct dcb_output *, int crtc); bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); uint8_t *nouveau_bios_embedded_edid(struct drm_device *); int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, Loading Loading
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c +33 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,10 @@ * Authors: Ben Skeggs */ #include <subdev/bios.h> #include <subdev/bios/dcb.h> #include <subdev/bios/disp.h> #include <subdev/bios/init.h> #include <subdev/devinit.h> #include <subdev/vga.h> Loading Loading @@ -55,7 +59,12 @@ nv50_devinit_dtor(struct nouveau_object *object) static int nv50_devinit_init(struct nouveau_object *object) { struct nouveau_bios *bios = nouveau_bios(object); struct nv50_devinit_priv *priv = (void *)object; struct nvbios_outp info; struct dcb_output outp; u8 ver = 0xff, hdr, cnt, len; int ret, i = 0; if (!priv->base.post) { if (!nv_rdvgac(priv, 0, 0x00) && Loading @@ -65,7 +74,30 @@ nv50_devinit_init(struct nouveau_object *object) } } return nouveau_devinit_init(&priv->base); ret = nouveau_devinit_init(&priv->base); if (ret) return ret; /* if we ran the init tables, execute first script pointer for each * display table output entry that has a matching dcb entry. */ while (priv->base.post && ver) { u16 data = nvbios_outp_parse(bios, i++, &ver, &hdr, &cnt, &len, &info); if (data && dcb_outp_match(bios, info.type, info.mask, &ver, &len, &outp)) { struct nvbios_init init = { .subdev = nv_subdev(priv), .bios = bios, .offset = info.script[0], .outp = &outp, .crtc = -1, .execute = 1, }; nvbios_exec(&init); } }; return 0; } static int Loading
drivers/gpu/drm/nouveau/nouveau_bios.c +1 −206 Original line number Diff line number Diff line Loading @@ -652,178 +652,6 @@ bios_encoder_match(struct dcb_output *dcb, u32 hash) } } int nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, struct dcb_output *dcbent, int crtc) { /* * The display script table is located by the BIT 'U' table. * * It contains an array of pointers to various tables describing * a particular output type. The first 32-bits of the output * tables contains similar information to a DCB entry, and is * used to decide whether that particular table is suitable for * the output you want to access. * * The "record header length" field here seems to indicate the * offset of the first configuration entry in the output tables. * This is 10 on most cards I've seen, but 12 has been witnessed * on DP cards, and there's another script pointer within the * header. * * offset + 0 ( 8 bits): version * offset + 1 ( 8 bits): header length * offset + 2 ( 8 bits): record length * offset + 3 ( 8 bits): number of records * offset + 4 ( 8 bits): record header length * offset + 5 (16 bits): pointer to first output script table */ struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; uint8_t *table = &bios->data[bios->display.script_table_ptr]; uint8_t *otable = NULL; uint16_t script; int i; if (!bios->display.script_table_ptr) { NV_ERROR(drm, "No pointer to output script table\n"); return 1; } /* * Nothing useful has been in any of the pre-2.0 tables I've seen, * so until they are, we really don't need to care. */ if (table[0] < 0x20) return 1; if (table[0] != 0x20 && table[0] != 0x21) { NV_ERROR(drm, "Output script table version 0x%02x unknown\n", table[0]); return 1; } /* * The output script tables describing a particular output type * look as follows: * * offset + 0 (32 bits): output this table matches (hash of DCB) * offset + 4 ( 8 bits): unknown * offset + 5 ( 8 bits): number of configurations * offset + 6 (16 bits): pointer to some script * offset + 8 (16 bits): pointer to some script * * headerlen == 10 * offset + 10 : configuration 0 * * headerlen == 12 * offset + 10 : pointer to some script * offset + 12 : configuration 0 * * Each config entry is as follows: * * offset + 0 (16 bits): unknown, assumed to be a match value * offset + 2 (16 bits): pointer to script table (clock set?) * offset + 4 (16 bits): pointer to script table (reset?) * * There doesn't appear to be a count value to say how many * entries exist in each script table, instead, a 0 value in * the first 16-bit word seems to indicate both the end of the * list and the default entry. The second 16-bit word in the * script tables is a pointer to the script to execute. */ NV_DEBUG(drm, "Searching for output entry for %d %d %d\n", dcbent->type, dcbent->location, dcbent->or); for (i = 0; i < table[3]; i++) { otable = ROMPTR(dev, table[table[1] + (i * table[2])]); if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) break; } if (!otable) { NV_DEBUG(drm, "failed to match any output table\n"); return 1; } if (pclk < -2 || pclk > 0) { /* Try to find matching script table entry */ for (i = 0; i < otable[5]; i++) { if (ROM16(otable[table[4] + i*6]) == type) break; } if (i == otable[5]) { NV_ERROR(drm, "Table 0x%04x not found for %d/%d, " "using first\n", type, dcbent->type, dcbent->or); i = 0; } } if (pclk == 0) { script = ROM16(otable[6]); if (!script) { NV_DEBUG(drm, "output script 0 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing output script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk == -1) { script = ROM16(otable[8]); if (!script) { NV_DEBUG(drm, "output script 1 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing output script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk == -2) { if (table[4] >= 12) script = ROM16(otable[10]); else script = 0; if (!script) { NV_DEBUG(drm, "output script 2 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing output script 2\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk > 0) { script = ROM16(otable[table[4] + i*6 + 2]); if (script) script = clkcmptable(bios, script, pclk); if (!script) { NV_DEBUG(drm, "clock script 0 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing clock script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } else if (pclk < 0) { script = ROM16(otable[table[4] + i*6 + 4]); if (script) script = clkcmptable(bios, script, -pclk); if (!script) { NV_DEBUG(drm, "clock script 1 not found\n"); return 1; } NV_DEBUG(drm, "0x%04X: parsing clock script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent, crtc); } return 0; } int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, int pxclk) { /* Loading Loading @@ -1212,31 +1040,6 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, return 0; } static int parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) { /* * Parses the pointer to the G80 output script tables * * Starting at bitentry->offset: * * offset + 0 (16 bits): output script table pointer */ struct nouveau_drm *drm = nouveau_drm(dev); uint16_t outputscripttableptr; if (bitentry->length != 3) { NV_ERROR(drm, "Do not understand BIT U table\n"); return -EINVAL; } outputscripttableptr = ROM16(bios->data[bitentry->offset]); bios->display.script_table_ptr = outputscripttableptr; return 0; } struct bit_table { const char id; int (* const parse_fn)(struct drm_device *, struct nvbios *, struct bit_entry *); Loading Loading @@ -1313,7 +1116,6 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) parse_bit_table(bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */ parse_bit_table(bios, bitoffset, &BIT_TABLE('L', lvds)); parse_bit_table(bios, bitoffset, &BIT_TABLE('T', tmds)); parse_bit_table(bios, bitoffset, &BIT_TABLE('U', U)); return 0; } Loading Loading @@ -2324,7 +2126,7 @@ nouveau_run_vbios_init(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; int i, ret = 0; int ret = 0; /* Reset the BIOS head to 0. */ bios->state.crtchead = 0; Loading @@ -2337,13 +2139,6 @@ nouveau_run_vbios_init(struct drm_device *dev) bios->fp.lvds_init_run = false; } if (nv_device(drm->device)->card_type >= NV_50) { for (i = 0; bios->execute && i < bios->dcb.entries; i++) { nouveau_bios_run_display_table(dev, 0, 0, &bios->dcb.entry[i], -1); } } return ret; } Loading
drivers/gpu/drm/nouveau/nouveau_bios.h +0 −8 Original line number Diff line number Diff line Loading @@ -127,12 +127,6 @@ struct nvbios { int crtchead; } state; struct { struct dcb_output *output; int crtc; uint16_t script_table_ptr; } display; struct { uint16_t fptablepointer; /* also used by tmds */ uint16_t fpxlatetableptr; Loading Loading @@ -185,8 +179,6 @@ void nouveau_bios_takedown(struct drm_device *dev); int nouveau_run_vbios_init(struct drm_device *); struct dcb_connector_table_entry * nouveau_bios_connector_entry(struct drm_device *, int index); int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, struct dcb_output *, int crtc); bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); uint8_t *nouveau_bios_embedded_edid(struct drm_device *); int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, Loading