From e495d0d7e36298f76336fdc58685ac4cacd454ba Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 23 Jan 2012 13:22:58 +1000 Subject: drm/nv50/disp: more accurate function to determine active crtcs Signed-off-by: Ben Skeggs Signed-off-by: Martin Peres --- drivers/gpu/drm/nouveau/nv50_display.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nv50_display.c') diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 7ba28e08ee31..ce440e2e58ca 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -50,6 +50,29 @@ nv50_sor_nr(struct drm_device *dev) return 4; } +u32 +nv50_display_active_crtcs(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 mask = 0; + int i; + + if (dev_priv->chipset < 0x90 || + dev_priv->chipset == 0x92 || + dev_priv->chipset == 0xa0) { + for (i = 0; i < 2; i++) + mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); + } else { + for (i = 0; i < 4; i++) + mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); + } + + for (i = 0; i < 3; i++) + mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); + + return mask & 3; +} + static int evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data) { -- cgit v1.2.3 From 8663bc7cde00c8e832d985354f8a6d57a52f7d92 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 9 Mar 2012 16:22:56 +1000 Subject: drm/nouveau/dp: move all nv50/sor-specific code out of nouveau_dp.c Off-chip encoders (which we don't support yet anyway), and newer chipsets (such as NVD9...), will need their own code for this. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_dp.c | 233 ++---------------------------- drivers/gpu/drm/nouveau/nouveau_drv.h | 8 - drivers/gpu/drm/nouveau/nouveau_encoder.h | 18 +++ drivers/gpu/drm/nouveau/nv50_display.c | 4 +- drivers/gpu/drm/nouveau/nv50_sor.c | 196 ++++++++++++++++++++++++- 5 files changed, 231 insertions(+), 228 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nv50_display.c') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 1a613ab4e08f..f38f561a0058 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -161,116 +161,6 @@ out: return ret; } -static u32 -dp_link_bw_get(struct drm_device *dev, int or, int link) -{ - u32 ctrl = nv_rd32(dev, 0x614300 + (or * 0x800)); - if (!(ctrl & 0x000c0000)) - return 162000; - return 270000; -} - -static int -dp_lane_count_get(struct drm_device *dev, int or, int link) -{ - u32 ctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); - switch (ctrl & 0x000f0000) { - case 0x00010000: return 1; - case 0x00030000: return 2; - default: - return 4; - } -} - -void -nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) -{ - const u32 symbol = 100000; - int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; - int TU, VTUi, VTUf, VTUa; - u64 link_data_rate, link_ratio, unk; - u32 best_diff = 64 * symbol; - u32 link_nr, link_bw, r; - - /* calculate packed data rate for each lane */ - link_nr = dp_lane_count_get(dev, or, link); - link_data_rate = (clk * bpp / 8) / link_nr; - - /* calculate ratio of packed data rate to link symbol rate */ - link_bw = dp_link_bw_get(dev, or, link); - link_ratio = link_data_rate * symbol; - r = do_div(link_ratio, link_bw); - - for (TU = 64; TU >= 32; TU--) { - /* calculate average number of valid symbols in each TU */ - u32 tu_valid = link_ratio * TU; - u32 calc, diff; - - /* find a hw representation for the fraction.. */ - VTUi = tu_valid / symbol; - calc = VTUi * symbol; - diff = tu_valid - calc; - if (diff) { - if (diff >= (symbol / 2)) { - VTUf = symbol / (symbol - diff); - if (symbol - (VTUf * diff)) - VTUf++; - - if (VTUf <= 15) { - VTUa = 1; - calc += symbol - (symbol / VTUf); - } else { - VTUa = 0; - VTUf = 1; - calc += symbol; - } - } else { - VTUa = 0; - VTUf = min((int)(symbol / diff), 15); - calc += symbol / VTUf; - } - - diff = calc - tu_valid; - } else { - /* no remainder, but the hw doesn't like the fractional - * part to be zero. decrement the integer part and - * have the fraction add a whole symbol back - */ - VTUa = 0; - VTUf = 1; - VTUi--; - } - - if (diff < best_diff) { - best_diff = diff; - bestTU = TU; - bestVTUa = VTUa; - bestVTUf = VTUf; - bestVTUi = VTUi; - if (diff == 0) - break; - } - } - - if (!bestTU) { - NV_ERROR(dev, "DP: unable to find suitable config\n"); - return; - } - - /* XXX close to vbios numbers, but not right */ - unk = (symbol - link_ratio) * bestTU; - unk *= link_ratio; - r = do_div(unk, symbol); - r = do_div(unk, symbol); - unk += 6; - - nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); - nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | - bestVTUf << 16 | - bestVTUi << 8 | - unk); -} - u8 * nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) { @@ -318,13 +208,10 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) * link training *****************************************************************************/ struct dp_state { + struct dp_train_func *func; struct dcb_entry *dcb; - u8 *table; - u8 *entry; int auxch; int crtc; - int or; - int link; u8 *dpcd; int link_nr; u32 link_bw; @@ -335,100 +222,48 @@ struct dp_state { static void dp_set_link_config(struct drm_device *dev, struct dp_state *dp) { - int or = dp->or, link = dp->link; - u8 *entry, sink[2]; - u32 dp_ctrl; - u16 script; + u8 sink[2]; NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); - /* set selected link rate on source */ - switch (dp->link_bw) { - case 270000: - nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00040000); - sink[0] = DP_LINK_BW_2_7; - break; - default: - nv_mask(dev, 0x614300 + (or * 0x800), 0x000c0000, 0x00000000); - sink[0] = DP_LINK_BW_1_62; - break; - } - - /* offset +0x0a of each dp encoder table entry is a pointer to another - * table, that has (among other things) pointers to more scripts that - * need to be executed, this time depending on link speed. - */ - entry = ROMPTR(dev, dp->entry[10]); - if (entry) { - if (dp->table[0] < 0x30) { - while (dp->link_bw < (ROM16(entry[0]) * 10)) - entry += 4; - script = ROM16(entry[2]); - } else { - while (dp->link_bw < (entry[0] * 27000)) - entry += 3; - script = ROM16(entry[1]); - } + /* set desired link configuration on the source */ + dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, + dp->dpcd[2] & DP_ENHANCED_FRAME_CAP); - nouveau_bios_run_init_table(dev, script, dp->dcb, dp->crtc); - } - - /* configure lane count on the source */ - dp_ctrl = ((1 << dp->link_nr) - 1) << 16; + /* inform the sink of the new configuration */ + sink[0] = dp->link_bw / 27000; sink[1] = dp->link_nr; - if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) { - dp_ctrl |= 0x00004000; + if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - } - - nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x001f4000, dp_ctrl); - /* inform the sink of the new configuration */ auxch_tx(dev, dp->auxch, 8, DP_LINK_BW_SET, sink, 2); } static void -dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 tp) +dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) { u8 sink_tp; - NV_DEBUG_KMS(dev, "training pattern %d\n", tp); + NV_DEBUG_KMS(dev, "training pattern %d\n", pattern); - nv_mask(dev, NV50_SOR_DP_CTRL(dp->or, dp->link), 0x0f000000, tp << 24); + dp->func->train_set(dev, dp->dcb, pattern); auxch_tx(dev, dp->auxch, 9, DP_TRAINING_PATTERN_SET, &sink_tp, 1); sink_tp &= ~DP_TRAINING_PATTERN_MASK; - sink_tp |= tp; + sink_tp |= pattern; auxch_tx(dev, dp->auxch, 8, DP_TRAINING_PATTERN_SET, &sink_tp, 1); } -static const u8 nv50_lane_map[] = { 16, 8, 0, 24 }; -static const u8 nvaf_lane_map[] = { 24, 16, 8, 0 }; - static int dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mask = 0, drv = 0, pre = 0, unk = 0; - const u8 *shifts; - int link = dp->link; - int or = dp->or; int i; - if (dev_priv->chipset != 0xaf) - shifts = nv50_lane_map; - else - shifts = nvaf_lane_map; - for (i = 0; i < dp->link_nr; i++) { - u8 *conf = dp->entry + dp->table[4]; u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; u8 lpre = (lane & 0x0c) >> 2; u8 lvsw = (lane & 0x03) >> 0; - mask |= 0xff << shifts[i]; - unk |= 1 << (shifts[i] >> 3); - dp->conf[i] = (lpre << 3) | lvsw; if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; @@ -436,41 +271,9 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); - - if (dp->table[0] < 0x30) { - u8 *last = conf + (dp->entry[4] * dp->table[5]); - while (lvsw != conf[0] || lpre != conf[1]) { - conf += dp->table[5]; - if (conf >= last) - return -EINVAL; - } - - conf += 2; - } else { - /* no lookup table anymore, set entries for each - * combination of voltage swing and pre-emphasis - * level allowed by the DP spec. - */ - switch (lvsw) { - case 0: lpre += 0; break; - case 1: lpre += 4; break; - case 2: lpre += 7; break; - case 3: lpre += 9; break; - } - - conf = conf + (lpre * dp->table[5]); - conf++; - } - - drv |= conf[0] << shifts[i]; - pre |= conf[1] << shifts[i]; - unk = (unk & ~0x0000ff00) | (conf[2] << 8); + dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); } - nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, drv); - nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, pre); - nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff0f, unk); - return auxch_tx(dev, dp->auxch, 8, DP_TRAINING_LANE0_SET, dp->conf, 4); } @@ -598,7 +401,8 @@ dp_link_train_fini(struct drm_device *dev, struct dp_state *dp) } bool -nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) +nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, + struct dp_train_func *func) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); @@ -614,15 +418,10 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) if (!auxch) return false; - dp.table = nouveau_dp_bios_data(dev, nv_encoder->dcb, &dp.entry); - if (!dp.table) - return -EINVAL; - + dp.func = func; dp.dcb = nv_encoder->dcb; dp.crtc = nv_crtc->index; dp.auxch = auxch->drive; - dp.or = nv_encoder->or; - dp.link = !(nv_encoder->dcb->sorconf.link & 1); dp.dpcd = nv_encoder->dp.dpcd; /* some sinks toggle hotplug in response to some of the actions diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 4bb6aeec91f6..cf0e74a2c667 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1162,14 +1162,6 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); /* nouveau_hdmi.c */ void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); -/* nouveau_dp.c */ -int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, - uint8_t *data, int data_nr); -bool nouveau_dp_detect(struct drm_encoder *); -bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate); -void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32); -u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); - /* nv04_fb.c */ extern int nv04_fb_vram_init(struct drm_device *); extern int nv04_fb_init(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index e5d6e3faff3d..fa431742271e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -32,6 +32,14 @@ #define NV_DPMS_CLEARED 0x80 +struct dp_train_func { + void (*link_set)(struct drm_device *, struct dcb_entry *, int crtc, + int nr, u32 bw, bool enhframe); + void (*train_set)(struct drm_device *, struct dcb_entry *, u8 pattern); + void (*train_adj)(struct drm_device *, struct dcb_entry *, + u8 lane, u8 swing, u8 preem); +}; + struct nouveau_encoder { struct drm_encoder_slave base; @@ -78,9 +86,19 @@ get_slave_funcs(struct drm_encoder *enc) return to_encoder_slave(enc)->slave_funcs; } +/* nouveau_dp.c */ +int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, + uint8_t *data, int data_nr); +bool nouveau_dp_detect(struct drm_encoder *); +bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate, + struct dp_train_func *); +u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **); + struct nouveau_connector * nouveau_encoder_connector_get(struct nouveau_encoder *encoder); int nv50_sor_create(struct drm_connector *, struct dcb_entry *); +void nv50_sor_dp_calc_tu(struct drm_device *, int, int, u32, u32); int nv50_dac_create(struct drm_connector *, struct dcb_entry *); + #endif /* __NOUVEAU_ENCODER_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index ce440e2e58ca..0e47a898f415 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -863,9 +863,9 @@ nv50_display_unk20_handler(struct drm_device *dev) if (type == OUTPUT_DP) { int link = !(dcb->dpconf.sor.link & 1); if ((mc & 0x000f0000) == 0x00020000) - nouveau_dp_tu_update(dev, or, link, pclk, 18); + nv50_sor_dp_calc_tu(dev, or, link, pclk, 18); else - nouveau_dp_tu_update(dev, or, link, pclk, 24); + nv50_sor_dp_calc_tu(dev, or, link, pclk, 24); } if (dcb->type != OUTPUT_ANALOG) { diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index c4423ba9c9bf..ba1b8cc03545 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -36,6 +36,193 @@ #include "nouveau_crtc.h" #include "nv50_display.h" +static u32 +nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ + static const u8 nv50[] = { 16, 8, 0, 24 }; + if (dev_priv->card_type == 0xaf) + return nvaf[lane]; + return nv50[lane]; +} + +static void +nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern) +{ + u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); +} + +static void +nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb, + u8 lane, u8 swing, u8 preem) +{ + u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + u32 shift = nv50_sor_dp_lane_map(dev, dcb, lane); + u32 mask = 0x000000ff << shift; + u8 *table, *entry, *config; + + table = nouveau_dp_bios_data(dev, dcb, &entry); + if (!table || (table[0] != 0x20 && table[0] != 0x21)) { + NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); + return; + } + + config = entry + table[4]; + while (config[0] != swing || config[1] != preem) { + config += table[5]; + if (config >= entry + table[4] + entry[4] * table[5]) + return; + } + + nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, config[2] << shift); + nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, config[3] << shift); + nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8); +} + +static void +nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc, + int link_nr, u32 link_bw, bool enhframe) +{ + u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000; + u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)) & ~0x000c0000; + u8 *table, *entry, mask; + int i; + + table = nouveau_dp_bios_data(dev, dcb, &entry); + if (!table || (table[0] != 0x20 && table[0] != 0x21)) { + NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); + return; + } + + entry = ROMPTR(dev, entry[10]); + if (entry) { + while (link_bw < ROM16(entry[0]) * 10) + entry += 4; + + nouveau_bios_run_init_table(dev, ROM16(entry[2]), dcb, crtc); + } + + dpctrl |= ((1 << link_nr) - 1) << 16; + if (enhframe) + dpctrl |= 0x00004000; + + if (link_bw > 162000) + clksor |= 0x00040000; + + nv_wr32(dev, 0x614300 + (or * 0x800), clksor); + nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), dpctrl); + + mask = 0; + for (i = 0; i < link_nr; i++) + mask |= 1 << (nv50_sor_dp_lane_map(dev, dcb, i) >> 3); + nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask); +} + +static void +nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) +{ + u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & 0x000f0000; + u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)); + if (clksor & 0x000c0000) + *bw = 270000; + else + *bw = 162000; + + if (dpctrl > 0x00030000) *nr = 4; + else if (dpctrl > 0x00010000) *nr = 2; + else *nr = 1; +} + +void +nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) +{ + const u32 symbol = 100000; + int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; + int TU, VTUi, VTUf, VTUa; + u64 link_data_rate, link_ratio, unk; + u32 best_diff = 64 * symbol; + u32 link_nr, link_bw, r; + + /* calculate packed data rate for each lane */ + nv50_sor_dp_link_get(dev, or, link, &link_nr, &link_bw); + link_data_rate = (clk * bpp / 8) / link_nr; + + /* calculate ratio of packed data rate to link symbol rate */ + link_ratio = link_data_rate * symbol; + r = do_div(link_ratio, link_bw); + + for (TU = 64; TU >= 32; TU--) { + /* calculate average number of valid symbols in each TU */ + u32 tu_valid = link_ratio * TU; + u32 calc, diff; + + /* find a hw representation for the fraction.. */ + VTUi = tu_valid / symbol; + calc = VTUi * symbol; + diff = tu_valid - calc; + if (diff) { + if (diff >= (symbol / 2)) { + VTUf = symbol / (symbol - diff); + if (symbol - (VTUf * diff)) + VTUf++; + + if (VTUf <= 15) { + VTUa = 1; + calc += symbol - (symbol / VTUf); + } else { + VTUa = 0; + VTUf = 1; + calc += symbol; + } + } else { + VTUa = 0; + VTUf = min((int)(symbol / diff), 15); + calc += symbol / VTUf; + } + + diff = calc - tu_valid; + } else { + /* no remainder, but the hw doesn't like the fractional + * part to be zero. decrement the integer part and + * have the fraction add a whole symbol back + */ + VTUa = 0; + VTUf = 1; + VTUi--; + } + + if (diff < best_diff) { + best_diff = diff; + bestTU = TU; + bestVTUa = VTUa; + bestVTUf = VTUf; + bestVTUi = VTUi; + if (diff == 0) + break; + } + } + + if (!bestTU) { + NV_ERROR(dev, "DP: unable to find suitable config\n"); + return; + } + + /* XXX close to vbios numbers, but not right */ + unk = (symbol - link_ratio) * bestTU; + unk *= link_ratio; + r = do_div(unk, symbol); + r = do_div(unk, symbol); + unk += 6; + + nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); + nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | + bestVTUf << 16 | + bestVTUi << 8 | + unk); +} static void nv50_sor_disconnect(struct drm_encoder *encoder) { @@ -124,9 +311,16 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) return; if (mode == DRM_MODE_DPMS_ON) { + struct dp_train_func func = { + .link_set = nv50_sor_dp_link_set, + .train_set = nv50_sor_dp_train_set, + .train_adj = nv50_sor_dp_train_adj + }; + u32 rate = nv_encoder->dp.datarate; u8 status = DP_SET_POWER_D0; + nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); - nouveau_dp_link_train(encoder, nv_encoder->dp.datarate); + nouveau_dp_link_train(encoder, rate, &func); } else { u8 status = DP_SET_POWER_D3; nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1); -- cgit v1.2.3 From b5b2e5988bd18a2f6e3f192adf7439599de00d3f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 16 Mar 2012 00:09:54 +1000 Subject: drm/nouveau: remove subchannel names from places where it doesn't matter These are FIFO methods, it doesn't matter what subchannel is being used. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.h | 23 ++++++++++++++++++----- drivers/gpu/drm/nouveau/nouveau_fence.c | 24 ++++++++++++------------ drivers/gpu/drm/nouveau/nv50_display.c | 12 ++++++------ drivers/gpu/drm/nouveau/nvd0_display.c | 4 ++-- 4 files changed, 38 insertions(+), 25 deletions(-) (limited to 'drivers/gpu/drm/nouveau/nv50_display.c') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 0df21752d274..eaf9872f9ee2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1763,13 +1763,26 @@ nv44_graph_class(struct drm_device *dev) #define NV_MEM_TYPE_VM 0x7f #define NV_MEM_COMP_VM 0x03 +/* FIFO methods */ +#define NV01_SUBCHAN_OBJECT 0x00000000 +#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH 0x00000010 +#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_LOW 0x00000014 +#define NV84_SUBCHAN_SEMAPHORE_SEQUENCE 0x00000018 +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER 0x0000001c +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL 0x00000001 +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 +#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 +#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 +#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 +#define NV10_SUBCHAN_REF_CNT 0x00000050 +#define NV11_SUBCHAN_DMA_SEMAPHORE 0x00000060 +#define NV11_SUBCHAN_SEMAPHORE_OFFSET 0x00000064 +#define NV11_SUBCHAN_SEMAPHORE_ACQUIRE 0x00000068 +#define NV11_SUBCHAN_SEMAPHORE_RELEASE 0x0000006c +#define NV40_SUBCHAN_YIELD 0x00000080 + /* NV_SW object class */ #define NV_SW 0x0000506e -#define NV_SW_DMA_SEMAPHORE 0x00000060 -#define NV_SW_SEMAPHORE_OFFSET 0x00000064 -#define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 -#define NV_SW_SEMAPHORE_RELEASE 0x0000006c -#define NV_SW_YIELD 0x00000080 #define NV_SW_DMA_VBLSEM 0x0000018c #define NV_SW_VBLSEM_OFFSET 0x00000400 #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 2f6daae68b9d..f676ecd3fd3c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -165,9 +165,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) if (USE_REFCNT(dev)) { if (dev_priv->card_type < NV_C0) - BEGIN_RING(chan, NvSubSw, 0x0050, 1); + BEGIN_RING(chan, 0, NV10_SUBCHAN_REF_CNT, 1); else - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0050, 1); + BEGIN_NVC0(chan, 2, 0, NV10_SUBCHAN_REF_CNT, 1); } else { BEGIN_RING(chan, NvSubSw, 0x0150, 1); } @@ -344,7 +344,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); + BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 3); OUT_RING (chan, NvSema); OUT_RING (chan, offset); OUT_RING (chan, 1); @@ -354,9 +354,9 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); OUT_RING (chan, chan->vram_handle); - BEGIN_RING(chan, NvSubSw, 0x0010, 4); + BEGIN_RING(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 1); @@ -366,7 +366,7 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) if (ret) return ret; - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 1); @@ -397,10 +397,10 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); + BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); OUT_RING (chan, NvSema); OUT_RING (chan, offset); - BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); + BEGIN_RING(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1); OUT_RING (chan, 1); } else if (dev_priv->chipset < 0xc0) { @@ -408,9 +408,9 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) if (ret) return ret; - BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); + BEGIN_RING(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); OUT_RING (chan, chan->vram_handle); - BEGIN_RING(chan, NvSubSw, 0x0010, 4); + BEGIN_RING(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 1); @@ -420,7 +420,7 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) if (ret) return ret; - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 1); @@ -510,7 +510,7 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) if (ret) return ret; - BEGIN_RING(chan, NvSubSw, 0, 1); + BEGIN_RING(chan, NvSubSw, NV01_SUBCHAN_OBJECT, 1); OUT_RING (chan, NvSw); FIRE_RING (chan); } diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 0e47a898f415..8b78b9cfa383 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -474,15 +474,15 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, } if (dev_priv->chipset < 0xc0) { - BEGIN_RING(chan, NvSubSw, 0x0060, 2); + BEGIN_RING(chan, 0, 0x0060, 2); OUT_RING (chan, NvEvoSema0 + nv_crtc->index); OUT_RING (chan, dispc->sem.offset); - BEGIN_RING(chan, NvSubSw, 0x006c, 1); + BEGIN_RING(chan, 0, 0x006c, 1); OUT_RING (chan, 0xf00d0000 | dispc->sem.value); - BEGIN_RING(chan, NvSubSw, 0x0064, 2); + BEGIN_RING(chan, 0, 0x0064, 2); OUT_RING (chan, dispc->sem.offset ^ 0x10); OUT_RING (chan, 0x74b1e000); - BEGIN_RING(chan, NvSubSw, 0x0060, 1); + BEGIN_RING(chan, 0, 0x0060, 1); if (dev_priv->chipset < 0x84) OUT_RING (chan, NvSema); else @@ -490,12 +490,12 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, } else { u64 offset = chan->dispc_vma[nv_crtc->index].offset; offset += dispc->sem.offset; - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + BEGIN_NVC0(chan, 2, 0, 0x0010, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 0xf00d0000 | dispc->sem.value); OUT_RING (chan, 0x1002); - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + BEGIN_NVC0(chan, 2, 0, 0x0010, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset ^ 0x10)); OUT_RING (chan, 0x74b1e000); diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index dfb8a951cbbe..5e2b79bdcae0 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -303,12 +303,12 @@ nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, offset = chan->dispc_vma[nv_crtc->index].offset; offset += evo->sem.offset; - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 0xf00d0000 | evo->sem.value); OUT_RING (chan, 0x1002); - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); + BEGIN_NVC0(chan, 2, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset ^ 0x10)); OUT_RING (chan, 0x74b1e000); -- cgit v1.2.3