diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-11-19 03:08:47 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 00:12:01 -0500 |
commit | 2e5702aff39532662198459726c624d5eadbdd78 (patch) | |
tree | cf2f2bb23d82afe54ca0f722f74ad1e5ff4e2f60 | |
parent | 7f4a195fcbd8b16f25f1de7f1419414d7505daa5 (diff) |
drm/nouveau: fabricate DCB encoder table for iMac G4
In typical Apple fashion there's no standard information about what
encoders are present on this machine, this patch adds a quirk to
provide it.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 102 |
1 files changed, 38 insertions, 64 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index b2293576f278..d3046559bf05 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -6053,52 +6053,17 @@ static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb) | |||
6053 | return entry; | 6053 | return entry; |
6054 | } | 6054 | } |
6055 | 6055 | ||
6056 | static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) | 6056 | static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c, |
6057 | int heads, int or) | ||
6057 | { | 6058 | { |
6058 | struct dcb_entry *entry = new_dcb_entry(dcb); | 6059 | struct dcb_entry *entry = new_dcb_entry(dcb); |
6059 | 6060 | ||
6060 | entry->type = 0; | 6061 | entry->type = type; |
6061 | entry->i2c_index = i2c; | 6062 | entry->i2c_index = i2c; |
6062 | entry->heads = heads; | 6063 | entry->heads = heads; |
6063 | entry->location = DCB_LOC_ON_CHIP; | 6064 | if (type != OUTPUT_ANALOG) |
6064 | entry->or = 1; | 6065 | entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ |
6065 | } | 6066 | entry->or = or; |
6066 | |||
6067 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) | ||
6068 | { | ||
6069 | struct dcb_entry *entry = new_dcb_entry(dcb); | ||
6070 | |||
6071 | entry->type = 2; | ||
6072 | entry->i2c_index = LEGACY_I2C_PANEL; | ||
6073 | entry->heads = twoHeads ? 3 : 1; | ||
6074 | entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ | ||
6075 | entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */ | ||
6076 | entry->duallink_possible = false; /* SiI164 and co. are single link */ | ||
6077 | |||
6078 | #if 0 | ||
6079 | /* | ||
6080 | * For dvi-a either crtc probably works, but my card appears to only | ||
6081 | * support dvi-d. "nvidia" still attempts to program it for dvi-a, | ||
6082 | * doing the full fp output setup (program 0x6808.. fp dimension regs, | ||
6083 | * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880); | ||
6084 | * the monitor picks up the mode res ok and lights up, but no pixel | ||
6085 | * data appears, so the board manufacturer probably connected up the | ||
6086 | * sync lines, but missed the video traces / components | ||
6087 | * | ||
6088 | * with this introduction, dvi-a left as an exercise for the reader. | ||
6089 | */ | ||
6090 | fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads); | ||
6091 | #endif | ||
6092 | } | ||
6093 | |||
6094 | static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads) | ||
6095 | { | ||
6096 | struct dcb_entry *entry = new_dcb_entry(dcb); | ||
6097 | |||
6098 | entry->type = 1; | ||
6099 | entry->i2c_index = LEGACY_I2C_TV; | ||
6100 | entry->heads = twoHeads ? 3 : 1; | ||
6101 | entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ | ||
6102 | } | 6067 | } |
6103 | 6068 | ||
6104 | static bool | 6069 | static bool |
@@ -6365,8 +6330,36 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) | |||
6365 | return true; | 6330 | return true; |
6366 | } | 6331 | } |
6367 | 6332 | ||
6333 | static void | ||
6334 | fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) | ||
6335 | { | ||
6336 | struct dcb_table *dcb = &bios->dcb; | ||
6337 | int all_heads = (nv_two_heads(dev) ? 3 : 1); | ||
6338 | |||
6339 | #ifdef __powerpc__ | ||
6340 | /* Apple iMac G4 NV17 */ | ||
6341 | if (of_machine_is_compatible("PowerMac4,5")) { | ||
6342 | fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1); | ||
6343 | fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2); | ||
6344 | return; | ||
6345 | } | ||
6346 | #endif | ||
6347 | |||
6348 | /* Make up some sane defaults */ | ||
6349 | fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1); | ||
6350 | |||
6351 | if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) | ||
6352 | fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV, | ||
6353 | all_heads, 0); | ||
6354 | |||
6355 | else if (bios->tmds.output0_script_ptr || | ||
6356 | bios->tmds.output1_script_ptr) | ||
6357 | fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL, | ||
6358 | all_heads, 1); | ||
6359 | } | ||
6360 | |||
6368 | static int | 6361 | static int |
6369 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | 6362 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios) |
6370 | { | 6363 | { |
6371 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 6364 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
6372 | struct dcb_table *dcb = &bios->dcb; | 6365 | struct dcb_table *dcb = &bios->dcb; |
@@ -6386,12 +6379,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | |||
6386 | 6379 | ||
6387 | /* this situation likely means a really old card, pre DCB */ | 6380 | /* this situation likely means a really old card, pre DCB */ |
6388 | if (dcbptr == 0x0) { | 6381 | if (dcbptr == 0x0) { |
6389 | NV_INFO(dev, "Assuming a CRT output exists\n"); | 6382 | fabricate_dcb_encoder_table(dev, bios); |
6390 | fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); | ||
6391 | |||
6392 | if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) | ||
6393 | fabricate_tv_output(dcb, twoHeads); | ||
6394 | |||
6395 | return 0; | 6383 | return 0; |
6396 | } | 6384 | } |
6397 | 6385 | ||
@@ -6451,21 +6439,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | |||
6451 | */ | 6439 | */ |
6452 | NV_TRACEWARN(dev, "No useful information in BIOS output table; " | 6440 | NV_TRACEWARN(dev, "No useful information in BIOS output table; " |
6453 | "adding all possible outputs\n"); | 6441 | "adding all possible outputs\n"); |
6454 | fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); | 6442 | fabricate_dcb_encoder_table(dev, bios); |
6455 | |||
6456 | /* | ||
6457 | * Attempt to detect TV before DVI because the test | ||
6458 | * for the former is more accurate and it rules the | ||
6459 | * latter out. | ||
6460 | */ | ||
6461 | if (nv04_tv_identify(dev, | ||
6462 | bios->legacy.i2c_indices.tv) >= 0) | ||
6463 | fabricate_tv_output(dcb, twoHeads); | ||
6464 | |||
6465 | else if (bios->tmds.output0_script_ptr || | ||
6466 | bios->tmds.output1_script_ptr) | ||
6467 | fabricate_dvi_i_output(dcb, twoHeads); | ||
6468 | |||
6469 | return 0; | 6443 | return 0; |
6470 | } | 6444 | } |
6471 | 6445 | ||
@@ -6859,7 +6833,7 @@ nouveau_bios_init(struct drm_device *dev) | |||
6859 | if (ret) | 6833 | if (ret) |
6860 | return ret; | 6834 | return ret; |
6861 | 6835 | ||
6862 | ret = parse_dcb_table(dev, bios, nv_two_heads(dev)); | 6836 | ret = parse_dcb_table(dev, bios); |
6863 | if (ret) | 6837 | if (ret) |
6864 | return ret; | 6838 | return ret; |
6865 | 6839 | ||