Commit 5d56fe5f authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-next' of...

Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-core-next

* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (102 commits)
  drm/nouveau/ttm: fix crash as a result of a recent ttm change
  drm/nouveau: Fix notifier blocks over the 4GB mark.
  drm/nouveau: Fix pushbufs over the 4GB mark.
  drm/nvc0/pm: initial engine reclocking
  drm/nouveau: move hpd enable/disable to common code
  drm/nv40/disp: implement support for hotplug irq
  drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues
  drm/nouveau: just pass gpio line to pwm_*, not entire gpio struct
  drm/nouveau/hwsq: remove some magic, give proper opcode names
  drm/nv50/pm: introduce hwsq-based memory reclocking
  drm/nv04/disp: handle dual-link spwg panels without needing quirks
  drm/nouveau/dp: remove broken display depth function, use the improved one
  drm/nouveau/mxm: implement ROM shadow method
  drm/nouveau/mxm: implement _DSM shadow method
  drm/nouveau/mxm: implement wmi shadow method
  drm/nouveau/mxm: initial implementation of dcb sanitisation
  drm/nouveau/disp: parse connector info directly in nouveau_connector.c
  drm/nouveau/i2c: handle bit-banging ourselves
  drm/nouveau/i2c: fix debug message
  drm/nouveau/i2c: tidy up bit-bang helpers, also fixing nv50 setsda bug
  ...
parents 4cf73129 f7b24c42
......@@ -9,9 +9,9 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
nouveau_dp.o nouveau_ramht.o \
nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \
nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \
nouveau_mm.o nouveau_vm.o \
nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \
nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \
......@@ -19,9 +19,12 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv04_graph.o nv10_graph.o nv20_graph.o \
nv40_graph.o nv50_graph.o nvc0_graph.o \
nv40_grctx.o nv50_grctx.o nvc0_grctx.o \
nv84_crypt.o \
nv84_crypt.o nv98_crypt.o \
nva3_copy.o nvc0_copy.o \
nv31_mpeg.o nv50_mpeg.o \
nv84_bsp.o \
nv84_vp.o \
nv98_ppp.o \
nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o \
......
This diff is collapsed.
......@@ -34,9 +34,14 @@
#define DCB_LOC_ON_CHIP 0
#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x))
#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x))
#define ROMPTR(bios, x) (ROM16(x) ? &(bios)->data[ROM16(x)] : NULL)
#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); })
#define ROM64(x) le64_to_cpu(*(u64 *)&(x))
#define ROMPTR(d,x) ({ \
struct drm_nouveau_private *dev_priv = (d)->dev_private; \
ROM16(x) ? &dev_priv->vbios.data[ROM16(x)] : NULL; \
})
struct bit_entry {
uint8_t id;
......@@ -48,30 +53,12 @@ struct bit_entry {
int bit_table(struct drm_device *, u8 id, struct bit_entry *);
struct dcb_i2c_entry {
uint32_t entry;
uint8_t port_type;
uint8_t read, write;
struct nouveau_i2c_chan *chan;
};
enum dcb_gpio_tag {
DCB_GPIO_TVDAC0 = 0xc,
DCB_GPIO_TVDAC1 = 0x2d,
};
struct dcb_gpio_entry {
enum dcb_gpio_tag tag;
int line;
bool invert;
uint32_t entry;
uint8_t state_default;
uint8_t state[2];
};
struct dcb_gpio_table {
int entries;
struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES];
DCB_GPIO_PWM_FAN = 0x9,
DCB_GPIO_FAN_SENSE = 0x3d,
DCB_GPIO_UNUSED = 0xff
};
enum dcb_connector_type {
......@@ -90,20 +77,6 @@ enum dcb_connector_type {
DCB_CONNECTOR_NONE = 0xff
};
struct dcb_connector_table_entry {
uint8_t index;
uint32_t entry;
enum dcb_connector_type type;
uint8_t index2;
uint8_t gpio_tag;
void *drm;
};
struct dcb_connector_table {
int entries;
struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES];
};
enum dcb_type {
OUTPUT_ANALOG = 0,
OUTPUT_TV = 1,
......@@ -111,6 +84,7 @@ enum dcb_type {
OUTPUT_LVDS = 3,
OUTPUT_DP = 6,
OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */
OUTPUT_UNUSED = 15,
OUTPUT_ANY = -1
};
......@@ -155,18 +129,8 @@ struct dcb_entry {
struct dcb_table {
uint8_t version;
int entries;
struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
uint8_t *i2c_table;
uint8_t i2c_default_indices;
struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
uint16_t gpio_table_ptr;
struct dcb_gpio_table gpio;
uint16_t connector_table_ptr;
struct dcb_connector_table connector;
};
enum nouveau_or {
......@@ -195,7 +159,7 @@ enum pll_types {
PLL_SHADER = 0x02,
PLL_UNK03 = 0x03,
PLL_MEMORY = 0x04,
PLL_UNK05 = 0x05,
PLL_VDEC = 0x05,
PLL_UNK40 = 0x40,
PLL_UNK41 = 0x41,
PLL_UNK42 = 0x42,
......@@ -333,4 +297,11 @@ struct nvbios {
} legacy;
};
void *dcb_table(struct drm_device *);
void *dcb_outp(struct drm_device *, u8 idx);
int dcb_outp_foreach(struct drm_device *, void *data,
int (*)(struct drm_device *, void *, int idx, u8 *outp));
u8 *dcb_conntab(struct drm_device *);
u8 *dcb_conn(struct drm_device *, u8 idx);
#endif
......@@ -682,8 +682,7 @@ nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo,
if (mem->mem_type == TTM_PL_VRAM)
nouveau_vm_map(vma, node);
else
nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT,
node, node->pages);
nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node);
return 0;
}
......@@ -810,7 +809,6 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
static void
nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
{
struct nouveau_mem *node = new_mem->mm_node;
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vma *vma;
......@@ -822,7 +820,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
nvbo->page_shift == vma->vm->spg_shift) {
nouveau_vm_map_sg(vma, 0, new_mem->
num_pages << PAGE_SHIFT,
node, node->pages);
new_mem->mm_node);
} else {
nouveau_vm_unmap(vma);
}
......@@ -1173,7 +1171,7 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
else
if (nvbo->bo.mem.mem_type == TTM_PL_TT)
nouveau_vm_map_sg(vma, 0, size, node, node->pages);
nouveau_vm_map_sg(vma, 0, size, node);
list_add_tail(&vma->head, &nvbo->vma_list);
vma->refcount = 1;
......
......@@ -187,6 +187,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
nouveau_dma_pre_init(chan);
chan->user_put = 0x40;
chan->user_get = 0x44;
if (dev_priv->card_type >= NV_50)
chan->user_get_hi = 0x60;
/* disable the fifo caches */
pfifo->reassign(dev, false);
......
This diff is collapsed.
......@@ -30,13 +30,43 @@
#include "drm_edid.h"
#include "nouveau_i2c.h"
enum nouveau_underscan_type {
UNDERSCAN_OFF,
UNDERSCAN_ON,
UNDERSCAN_AUTO,
};
/* the enum values specifically defined here match nv50/nvd0 hw values, and
* the code relies on this
*/
enum nouveau_dithering_mode {
DITHERING_MODE_OFF = 0x00,
DITHERING_MODE_ON = 0x01,
DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
DITHERING_MODE_AUTO
};
enum nouveau_dithering_depth {
DITHERING_DEPTH_6BPC = 0x00,
DITHERING_DEPTH_8BPC = 0x02,
DITHERING_DEPTH_AUTO
};
struct nouveau_connector {
struct drm_connector base;
enum dcb_connector_type type;
u8 index;
u8 *dcb;
u8 hpd;
struct dcb_connector_table_entry *dcb;
int dithering_mode;
int dithering_depth;
int scaling_mode;
bool use_dithering;
enum nouveau_underscan_type underscan;
u32 underscan_hborder;
u32 underscan_vborder;
struct nouveau_encoder *detected_encoder;
struct edid *edid;
......
......@@ -32,8 +32,6 @@ struct nouveau_crtc {
int index;
struct drm_display_mode *mode;
uint32_t dpms_saved_fp_control;
uint32_t fp_users;
int saturation;
......@@ -67,8 +65,8 @@ struct nouveau_crtc {
int depth;
} lut;
int (*set_dither)(struct nouveau_crtc *crtc, bool on, bool update);
int (*set_scale)(struct nouveau_crtc *crtc, int mode, bool update);
int (*set_dither)(struct nouveau_crtc *crtc, bool update);
int (*set_scale)(struct nouveau_crtc *crtc, bool update);
};
static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc)
......
......@@ -44,7 +44,7 @@ nouveau_debugfs_channel_info(struct seq_file *m, void *data)
seq_printf(m, "channel id : %d\n", chan->id);
seq_printf(m, "cpu fifo state:\n");
seq_printf(m, " base: 0x%08x\n", chan->pushbuf_base);
seq_printf(m, " base: 0x%10llx\n", chan->pushbuf_base);
seq_printf(m, " max: 0x%08x\n", chan->dma.max << 2);
seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2);
seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2);
......
......@@ -32,6 +32,8 @@
#include "nouveau_hw.h"
#include "nouveau_crtc.h"
#include "nouveau_dma.h"
#include "nouveau_connector.h"
#include "nouveau_gpio.h"
#include "nv50_display.h"
static void
......@@ -147,11 +149,186 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
return &nouveau_fb->base;
}
const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
.fb_create = nouveau_user_framebuffer_create,
.output_poll_changed = nouveau_fbcon_output_poll_changed,
};
struct drm_prop_enum_list {
u8 gen_mask;
int type;
char *name;
};
static struct drm_prop_enum_list underscan[] = {
{ 6, UNDERSCAN_AUTO, "auto" },
{ 6, UNDERSCAN_OFF, "off" },
{ 6, UNDERSCAN_ON, "on" },
{}
};
static struct drm_prop_enum_list dither_mode[] = {
{ 7, DITHERING_MODE_AUTO, "auto" },
{ 7, DITHERING_MODE_OFF, "off" },
{ 1, DITHERING_MODE_ON, "on" },
{ 6, DITHERING_MODE_STATIC2X2, "static 2x2" },
{ 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" },
{ 4, DITHERING_MODE_TEMPORAL, "temporal" },
{}
};
static struct drm_prop_enum_list dither_depth[] = {
{ 6, DITHERING_DEPTH_AUTO, "auto" },
{ 6, DITHERING_DEPTH_6BPC, "6 bpc" },
{ 6, DITHERING_DEPTH_8BPC, "8 bpc" },
{}
};
#define PROP_ENUM(p,gen,n,list) do { \
struct drm_prop_enum_list *l = (list); \
int c = 0; \
while (l->gen_mask) { \
if (l->gen_mask & (1 << (gen))) \
c++; \
l++; \
} \
if (c) { \
p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c); \
l = (list); \
c = 0; \
while (p && l->gen_mask) { \
if (l->gen_mask & (1 << (gen))) { \
drm_property_add_enum(p, c, l->type, l->name); \
c++; \
} \
l++; \
} \
} \
} while(0)
int
nouveau_display_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_display_engine *disp = &dev_priv->engine.display;
struct drm_connector *connector;
int ret;
ret = disp->init(dev);
if (ret)
return ret;
drm_kms_helper_poll_enable(dev);
/* enable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);
nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true);
}
return ret;
}
void
nouveau_display_fini(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_display_engine *disp = &dev_priv->engine.display;
struct drm_connector *connector;
/* disable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);
nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, false);
}
drm_kms_helper_poll_disable(dev);
disp->fini(dev);
}
int
nouveau_display_create(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_display_engine *disp = &dev_priv->engine.display;
int ret, gen;
drm_mode_config_init(dev);
drm_mode_create_scaling_mode_property(dev);
drm_mode_create_dvi_i_properties(dev);
if (dev_priv->card_type < NV_50)
gen = 0;
else
if (dev_priv->card_type < NV_D0)
gen = 1;
else
gen = 2;
PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode);
PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth);
PROP_ENUM(disp->underscan_property, gen, "underscan", underscan);
disp->underscan_hborder_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"underscan hborder", 2);
disp->underscan_hborder_property->values[0] = 0;
disp->underscan_hborder_property->values[1] = 128;
disp->underscan_vborder_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"underscan vborder", 2);
disp->underscan_vborder_property->values[0] = 0;
disp->underscan_vborder_property->values[1] = 128;
dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
if (dev_priv->card_type < NV_10) {
dev->mode_config.max_width = 2048;
dev->mode_config.max_height = 2048;
} else
if (dev_priv->card_type < NV_50) {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
} else {
dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192;
}
drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev);
ret = disp->create(dev);
if (ret)
return ret;
if (dev->mode_config.num_crtc) {
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
return ret;
}
return ret;
}
void
nouveau_display_destroy(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_display_engine *disp = &dev_priv->engine.display;
drm_vblank_cleanup(dev);
disp->destroy(dev);
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
}
int
nouveau_vblank_enable(struct drm_device *dev, int crtc)
{
......@@ -305,7 +482,10 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/* Emit a page flip */
if (dev_priv->card_type >= NV_50) {
ret = nv50_display_flip_next(crtc, fb, chan);
if (dev_priv->card_type >= NV_D0)
ret = nvd0_display_flip_next(crtc, fb, chan, 0);
else
ret = nv50_display_flip_next(crtc, fb, chan);
if (ret) {
nouveau_channel_put(&chan);
goto fail_unreserve;
......
......@@ -134,11 +134,13 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
* -EBUSY if timeout exceeded
*/
static inline int
READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
{
uint32_t val;
uint64_t val;
val = nvchan_rd32(chan, chan->user_get);
if (chan->user_get_hi)
val |= (uint64_t)nvchan_rd32(chan, chan->user_get_hi) << 32;
/* reset counter as long as GET is still advancing, this is
* to avoid misdetecting a GPU lockup if the GPU happens to
......@@ -218,8 +220,8 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
static int
nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
{
uint32_t cnt = 0, prev_get = 0;
int ret;
uint64_t prev_get = 0;
int ret, cnt = 0;
ret = nv50_dma_push_wait(chan, slots + 1);
if (unlikely(ret))
......@@ -261,8 +263,8 @@ nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
int
nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size)
{
uint32_t prev_get = 0, cnt = 0;
int get;
uint64_t prev_get = 0;
int cnt = 0, get;
if (chan->dma.ib_max)
return nv50_dma_wait(chan, slots, size);
......
......@@ -29,6 +29,7 @@
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include "nouveau_gpio.h"
/******************************************************************************
* aux channel util functions
......@@ -273,8 +274,6 @@ nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp)
u8 *
nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios;
struct bit_entry d;
u8 *table;
int i;
......@@ -289,7 +288,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
return NULL;
}
table = ROMPTR(bios, d.data[0]);
table = ROMPTR(dev, d.data[0]);
if (!table) {
NV_ERROR(dev, "displayport table pointer invalid\n");
return NULL;
......@@ -306,7 +305,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry)
}
for (i = 0; i < table[3]; i++) {
*entry = ROMPTR(bios, table[table[1] + (i * table[2])]);
*entry = ROMPTR(dev, table[table[1] + (i * table[2])]);
if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0])))
return table;
}
......@@ -336,7 +335,6 @@ struct dp_state {
static void
dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
int or = dp->or, link = dp->link;
u8 *entry, sink[2];
u32 dp_ctrl;
......@@ -360,7 +358,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
* table, that has (among other things) pointers to more scripts that
* need to be executed, this time depending on link speed.
*/
entry = ROMPTR(&dev_priv->vbios, dp->entry[10]);
entry = ROMPTR(dev, dp->entry[10]);
if (entry) {
if (dp->table[0] < 0x30) {
while (dp->link_bw < (ROM16(entry[0]) * 10))
......@@ -559,8 +557,6 @@ dp_link_train_eq(struct drm_device *dev, struct dp_state *dp)
bool
nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
{
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
struct nouveau_connector *nv_connector =
......@@ -581,7 +577,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
dp.dcb = nv_encoder->dcb;
dp.crtc = nv_crtc->index;
dp.auxch = auxch->rd;
dp.auxch = auxch->drive;
dp.or = nv_encoder->or;
dp.link = !(nv_encoder->dcb->sorconf.link & 1);
dp.dpcd = nv_encoder->dp.dpcd;
......@@ -590,7 +586,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
* we take during link training (DP_SET_POWER is one), we need
* to ignore them for the moment to avoid races.
*/
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false);
/* enable down-spreading, if possible */
if (dp.table[1] >= 16) {
......@@ -639,7 +635,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate)
nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc);
/* re-enable hotplug detect */
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true);
return true;
}
......@@ -656,7 +652,7 @@ nouveau_dp_detect(struct drm_encoder *encoder)
if (!auxch)
return false;
ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8);
ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8);
if (ret)
return false;
......@@ -684,7 +680,7 @@ int
nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
uint8_t *data, int data_nr)
{
return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr);
return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr);
}
static int
......
......@@ -124,6 +124,10 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
int nouveau_ctxfw;
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n");
int nouveau_mxmdcb = 1;
module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
int nouveau_fbpercrtc;
#if 0
module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400);
......@@ -178,8 +182,11 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
NV_INFO(dev, "Disabling fbcon acceleration...\n");
nouveau_fbcon_save_disable_accel(dev);
NV_INFO(dev, "Disabling display...\n");
nouveau_display_fini(dev);
NV_INFO(dev, "Disabling fbcon...\n");
nouveau_fbcon_set_suspend(dev, 1);
NV_INFO(dev, "Unpinning framebuffer(s)...\n");
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
......@@ -220,7 +227,7 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
ret = dev_priv->eng[e]->fini(dev, e, true);
if (ret) {
NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
NV_ERROR(dev, "... engine %d failed: %d\n", e, ret);
goto out_abort;
}
}
......@@ -246,10 +253,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pci_set_power_state(pdev, PCI_D3hot);
}
console_lock();
nouveau_fbcon_set_suspend(dev, 1);
console_unlock();
nouveau_fbcon_restore_accel(dev);
return 0;
out_abort:
......@@ -275,8 +278,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
nouveau_fbcon_save_disable_accel(dev);
NV_INFO(dev, "We're back, enabling device...\n");
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
......@@ -296,8 +297,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
if (ret)
return ret;
nouveau_pm_resume(dev);
if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
ret = nouveau_mem_init_agp(dev);
if (ret) {
......@@ -337,6 +336,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
}
}
nouveau_pm_resume(dev);
NV_INFO(dev, "Restoring mode...\n");
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_framebuffer *nouveau_fb;
......@@ -358,16 +359,10 @@ nouveau_pci_resume(struct pci_dev *pdev)
NV_ERROR(dev, "Could not pin/map cursor.\n");
}
engine->display.init(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
u32 offset = nv_crtc->cursor.nvbo->bo.offset;
nouveau_fbcon_set_suspend(dev, 0);
nouveau_fbcon_zfill_all(dev);
nv_crtc->cursor.set_offset(nv_crtc, offset);
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
nv_crtc->cursor_saved_y);
}
nouveau_display_init(dev);
/* Force CLUT to get re-loaded during modeset */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
......@@ -376,15 +371,17 @@ nouveau_pci_resume(struct pci_dev *pdev)
nv_crtc->lut.depth = 0;
}
console_lock();
nouveau_fbcon_set_suspend(dev, 0);
console_unlock();
drm_helper_resume_force_mode(dev);
nouveau_fbcon_zfill_all(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
u32 offset = nv_crtc->cursor.nvbo->bo.offset;
drm_helper_resume_force_mode(dev);
nv_crtc->cursor.set_offset(nv_crtc, offset);
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
nv_crtc->cursor_saved_y);
}
nouveau_fbcon_restore_accel(dev);
return 0;
}
......
This diff is collapsed.
......@@ -42,8 +42,6 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
return container_of(fb, struct nouveau_framebuffer, base);
}
extern const struct drm_mode_config_funcs nouveau_mode_config_funcs;
int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo);
#endif /* __NOUVEAU_FB_H__ */
......@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/screen_info.h>
#include <linux/vga_switcheroo.h>
#include <linux/console.h>
#include "drmP.h"
#include "drm.h"
......@@ -548,7 +549,13 @@ void nouveau_fbcon_restore_accel(struct drm_device *dev)
void nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
console_lock();
if (state == 0)
nouveau_fbcon_save_disable_accel(dev);
fb_set_suspend(dev_priv->nfbdev->helper.fbdev, state);
if (state == 1)
nouveau_fbcon_restore_accel(dev);
console_unlock();
}
void nouveau_fbcon_zfill_all(struct drm_device *dev)
......
This diff is collapsed.
/*
* Copyright 2011 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __NOUVEAU_GPIO_H__
#define __NOUVEAU_GPIO_H__
struct gpio_func {
u8 func;
u8 line;
u8 log[2];
};
/* nouveau_gpio.c */
int nouveau_gpio_create(struct drm_device *);
void nouveau_gpio_destroy(struct drm_device *);
int nouveau_gpio_init(struct drm_device *);
void nouveau_gpio_fini(struct drm_device *);
void nouveau_gpio_reset(struct drm_device *);
int nouveau_gpio_drive(struct drm_device *, int idx, int line,
int dir, int out);
int nouveau_gpio_sense(struct drm_device *, int idx, int line);
int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line,
struct gpio_func *);
int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state);
int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line);
int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on);
void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask);
int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line,
void (*)(void *, int state), void *data);
void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line,
void (*)(void *, int state), void *data);
static inline bool
nouveau_gpio_func_valid(struct drm_device *dev, u8 tag)
{
struct gpio_func func;
return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0;
}
static inline int
nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state)
{
return nouveau_gpio_set(dev, 0, tag, 0xff, state);
}
static inline int
nouveau_gpio_func_get(struct drm_device *dev, u8 tag)
{
return nouveau_gpio_get(dev, 0, tag, 0xff);
}
#endif
/*
* Copyright 2011 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
static bool
hdmi_sor(struct drm_encoder *encoder)
{
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
if (dev_priv->chipset < 0xa3)
return false;
return true;
}
static inline u32
hdmi_base(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
if (!hdmi_sor(encoder))
return 0x616500 + (nv_crtc->index * 0x800);
return 0x61c500 + (nv_encoder->or * 0x800);
}
static void
hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val)
{
nv_wr32(encoder->dev, hdmi_base(encoder) + reg, val);
}
static u32
hdmi_rd32(struct drm_encoder *encoder, u32 reg)
{
return nv_rd32(encoder->dev, hdmi_base(encoder) + reg);
}
static u32
hdmi_mask(struct drm_encoder *encoder, u32 reg, u32 mask, u32 val)
{
u32 tmp = hdmi_rd32(encoder, reg);
hdmi_wr32(encoder, reg, (tmp & ~mask) | val);
return tmp;
}
static void
nouveau_audio_disconnect(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct drm_device *dev = encoder->dev;
u32 or = nv_encoder->or * 0x800;
if (hdmi_sor(encoder)) {
nv_mask(dev, 0x61c448 + or, 0x00000003, 0x00000000);
}
}
static void
nouveau_audio_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_connector *nv_connector;
struct drm_device *dev = encoder->dev;
u32 or = nv_encoder->or * 0x800;
int i;
nv_connector = nouveau_encoder_connector_get(nv_encoder);
if (!drm_detect_monitor_audio(nv_connector->edid)) {
nouveau_audio_disconnect(encoder);
return;
}
if (hdmi_sor(encoder)) {
nv_mask(dev, 0x61c448 + or, 0x00000001, 0x00000001);
drm_edid_to_eld(&nv_connector->base, nv_connector->edid);
if (nv_connector->base.eld[0]) {
u8 *eld = nv_connector->base.eld;
for (i = 0; i < eld[2] * 4; i++)
nv_wr32(dev, 0x61c440 + or, (i << 8) | eld[i]);
for (i = eld[2] * 4; i < 0x60; i++)
nv_wr32(dev, 0x61c440 + or, (i << 8) | 0x00);
nv_mask(dev, 0x61c448 + or, 0x00000002, 0x00000002);
}
}
}
static void
nouveau_hdmi_infoframe(struct drm_encoder *encoder, u32 ctrl, u8 *frame)
{
/* calculate checksum for the infoframe */
u8 sum = 0, i;
for (i = 0; i < frame[2]; i++)
sum += frame[i];
frame[3] = 256 - sum;
/* disable infoframe, and write header */
hdmi_mask(encoder, ctrl + 0x00, 0x00000001, 0x00000000);
hdmi_wr32(encoder, ctrl + 0x08, *(u32 *)frame & 0xffffff);
/* register scans tell me the audio infoframe has only one set of
* subpack regs, according to tegra (gee nvidia, it'd be nice if we
* could get those docs too!), the hdmi block pads out the rest of
* the packet on its own.
*/
if (ctrl == 0x020)
frame[2] = 6;
/* write out checksum and data, weird weird 7 byte register pairs */
for (i = 0; i < frame[2] + 1; i += 7) {
u32 rsubpack = ctrl + 0x0c + ((i / 7) * 8);
u32 *subpack = (u32 *)&frame[3 + i];
hdmi_wr32(encoder, rsubpack + 0, subpack[0]);
hdmi_wr32(encoder, rsubpack + 4, subpack[1] & 0xffffff);
}
/* enable the infoframe */
hdmi_mask(encoder, ctrl, 0x00000001, 0x00000001);
}
static void
nouveau_hdmi_video_infoframe(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
const u8 Y = 0, A = 0, B = 0, S = 0, C = 0, M = 0, R = 0;
const u8 ITC = 0, EC = 0, Q = 0, SC = 0, VIC = 0, PR = 0;
const u8 bar_top = 0, bar_bottom = 0, bar_left = 0, bar_right = 0;
u8 frame[20];
frame[0x00] = 0x82; /* AVI infoframe */
frame[0x01] = 0x02; /* version */
frame[0x02] = 0x0d; /* length */
frame[0x03] = 0x00;
frame[0x04] = (Y << 5) | (A << 4) | (B << 2) | S;
frame[0x05] = (C << 6) | (M << 4) | R;
frame[0x06] = (ITC << 7) | (EC << 4) | (Q << 2) | SC;
frame[0x07] = VIC;
frame[0x08] = PR;
frame[0x09] = bar_top & 0xff;
frame[0x0a] = bar_top >> 8;
frame[0x0b] = bar_bottom & 0xff;
frame[0x0c] = bar_bottom >> 8;
frame[0x0d] = bar_left & 0xff;
frame[0x0e] = bar_left >> 8;
frame[0x0f] = bar_right & 0xff;
frame[0x10] = bar_right >> 8;
frame[0x11] = 0x00;
frame[0x12] = 0x00;
frame[0x13] = 0x00;
nouveau_hdmi_infoframe(encoder, 0x020, frame);
}
static void
nouveau_hdmi_audio_infoframe(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
const u8 CT = 0x00, CC = 0x01, ceaSS = 0x00, SF = 0x00, FMT = 0x00;
const u8 CA = 0x00, DM_INH = 0, LSV = 0x00;
u8 frame[12];
frame[0x00] = 0x84; /* Audio infoframe */
frame[0x01] = 0x01; /* version */
frame[0x02] = 0x0a; /* length */
frame[0x03] = 0x00;
frame[0x04] = (CT << 4) | CC;
frame[0x05] = (SF << 2) | ceaSS;
frame[0x06] = FMT;
frame[0x07] = CA;
frame[0x08] = (DM_INH << 7) | (LSV << 3);
frame[0x09] = 0x00;
frame[0x0a] = 0x00;
frame[0x0b] = 0x00;
nouveau_hdmi_infoframe(encoder, 0x000, frame);
}
static void
nouveau_hdmi_disconnect(struct drm_encoder *encoder)
{
nouveau_audio_disconnect(encoder);
/* disable audio and avi infoframes */
hdmi_mask(encoder, 0x000, 0x00000001, 0x00000000);
hdmi_mask(encoder, 0x020, 0x00000001, 0x00000000);
/* disable hdmi */
hdmi_mask(encoder, 0x0a4, 0x40000000, 0x00000000);
}
void
nouveau_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_connector *nv_connector;
struct drm_device *dev = encoder->dev;
u32 max_ac_packet, rekey;
nv_connector = nouveau_encoder_connector_get(nv_encoder);
if (!mode || !nv_connector || !nv_connector->edid ||
!drm_detect_hdmi_monitor(nv_connector->edid)) {
nouveau_hdmi_disconnect(encoder);
return;
}
nouveau_hdmi_video_infoframe(encoder, mode);
nouveau_hdmi_audio_infoframe(encoder, mode);
hdmi_mask(encoder, 0x0d0, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
nv_mask(dev, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
nv_mask(dev, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
nv_mask(dev, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
/* value matches nvidia binary driver, and tegra constant */
rekey = 56;
max_ac_packet = mode->htotal - mode->hdisplay;
max_ac_packet -= rekey;
max_ac_packet -= 18; /* constant from tegra */
max_ac_packet /= 32;
/* enable hdmi */
hdmi_mask(encoder, 0x0a4, 0x5f1f003f, 0x40000000 | /* enable */
0x1f000000 | /* unknown */
max_ac_packet << 16 |
rekey);
nouveau_audio_mode_set(encoder, mode);
}
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#ifndef __NOUVEAU_HWSQ_H__
#define __NOUVEAU_HWSQ_H__
struct hwsq_ucode {
u8 data[0x200];
union {
u8 *u08;
u16 *u16;
u32 *u32;
} ptr;
u16 len;
u32 reg;
u32 val;
};
static inline void
hwsq_init(struct hwsq_ucode *hwsq)
{
hwsq->ptr.u08 = hwsq->data;
hwsq->reg = 0xffffffff;
hwsq->val = 0xffffffff;
}
static inline void
hwsq_fini(struct hwsq_ucode *hwsq)
{
do {
*hwsq->ptr.u08++ = 0x7f;
hwsq->len = hwsq->ptr.u08 - hwsq->data;
} while (hwsq->len & 3);
hwsq->ptr.u08 = hwsq->data;
}
static inline void
hwsq_usec(struct hwsq_ucode *hwsq, u8 usec)
{
u32 shift = 0;
while (usec & ~3) {
usec >>= 2;
shift++;
}
*hwsq->ptr.u08++ = (shift << 2) | usec;
}
static inline void
hwsq_setf(struct hwsq_ucode *hwsq, u8 flag, int val)
{
flag += 0x80;
if (val >= 0)
flag += 0x20;
if (val >= 1)
flag += 0x20;
*hwsq->ptr.u08++ = flag;
}
static inline void
hwsq_op5f(struct hwsq_ucode *hwsq, u8 v0, u8 v1)
{
*hwsq->ptr.u08++ = 0x5f;
*hwsq->ptr.u08++ = v0;
*hwsq->ptr.u08++ = v1;
}
static inline void
hwsq_wr32(struct hwsq_ucode *hwsq, u32 reg, u32 val)
{
if (val != hwsq->val) {
if ((val & 0xffff0000) == (hwsq->val & 0xffff0000)) {
*hwsq->ptr.u08++ = 0x42;
*hwsq->ptr.u16++ = (val & 0x0000ffff);
} else {
*hwsq->ptr.u08++ = 0xe2;
*hwsq->ptr.u32++ = val;
}
hwsq->val = val;
}
if ((reg & 0xffff0000) == (hwsq->reg & 0xffff0000)) {
*hwsq->ptr.u08++ = 0x40;
*hwsq->ptr.u16++ = (reg & 0x0000ffff);
} else {
*hwsq->ptr.u08++ = 0xe0;
*hwsq->ptr.u32++ = reg;
}
hwsq->reg = reg;
}
#endif
This diff is collapsed.
......@@ -27,20 +27,25 @@
#include <linux/i2c-algo-bit.h>
#include "drm_dp_helper.h"
struct dcb_i2c_entry;
#define NV_I2C_PORT(n) (0x00 + (n))
#define NV_I2C_PORT_NUM 0x10
#define NV_I2C_DEFAULT(n) (0x80 + (n))
struct nouveau_i2c_chan {
struct i2c_adapter adapter;
struct drm_device *dev;
struct i2c_algo_bit_data bit;
unsigned rd;
unsigned wr;
unsigned data;
struct list_head head;
u8 index;
u8 type;
u32 dcb;
u32 drive;
u32 sense;
u32 state;
};
int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
int nouveau_i2c_init(struct drm_device *);
void nouveau_i2c_fini(struct drm_device *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index);
bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
int nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info,
......
......@@ -644,10 +644,10 @@ nouveau_mem_timing_init(struct drm_device *dev)
return;
if (P.version == 1)
hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]);
hdr = (struct nouveau_pm_tbl_header *) ROMPTR(dev, P.data[4]);
else
if (P.version == 2)
hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]);
hdr = (struct nouveau_pm_tbl_header *) ROMPTR(dev, P.data[8]);
else {
NV_WARN(dev, "unknown mem for BIT P %d\n", P.version);
}
......
This diff is collapsed.
......@@ -115,7 +115,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *nobj = NULL;
struct drm_mm_node *mem;
uint32_t offset;
uint64_t offset;
int target, ret;
mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0,
......
......@@ -723,14 +723,14 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm)
nv_wo32(chan->ramin, 0x020c, 0x000000ff);
/* map display semaphore buffers into channel's vm */
if (dev_priv->card_type >= NV_D0)
return 0;
for (i = 0; i < 2; i++) {
struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i];
ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm,
&chan->dispc_vma[i]);
for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nouveau_bo *bo;
if (dev_priv->card_type >= NV_D0)
bo = nvd0_display_crtc_sema(dev, i);
else
bo = nv50_display(dev)->crtc[i].sem.bo;
ret = nouveau_bo_vma_add(bo, chan->vm, &chan->dispc_vma[i]);
if (ret)
return ret;
}
......@@ -879,9 +879,14 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
NV_DEBUG(dev, "ch%d\n", chan->id);
if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) {
if (dev_priv->card_type >= NV_D0) {
for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i);
nouveau_bo_vma_del(bo, &chan->dispc_vma[i]);
}
} else
if (dev_priv->card_type >= NV_50) {
struct nv50_display *disp = nv50_display(dev);
for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nv50_display_crtc *dispc = &disp->crtc[i];
nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
......
......@@ -41,7 +41,7 @@ legacy_perf_init(struct drm_device *dev)
return;
}
perf = ROMPTR(bios, bmp[0x73]);
perf = ROMPTR(dev, bmp[0x73]);
if (!perf) {
NV_DEBUG(dev, "No memclock table pointer found.\n");
return;
......@@ -87,7 +87,7 @@ nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P,
* ramcfg to select the correct subentry
*/
if (P->version == 2) {
u8 *tmap = ROMPTR(bios, P->data[4]);
u8 *tmap = ROMPTR(dev, P->data[4]);
if (!tmap) {
NV_DEBUG(dev, "no timing map pointer\n");
return NULL;
......@@ -140,7 +140,6 @@ nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P,
struct nouveau_pm_level *perflvl)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios;
u8 *vmap;
int id;
......@@ -165,7 +164,7 @@ nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P,
return;
}
vmap = ROMPTR(bios, P->data[32]);
vmap = ROMPTR(dev, P->data[32]);
if (!vmap) {
NV_DEBUG(dev, "volt map table pointer invalid\n");
return;
......@@ -200,12 +199,14 @@ nouveau_perf_init(struct drm_device *dev)
return;
}
perf = ROMPTR(bios, P.data[0]);
perf = ROMPTR(dev, P.data[0]);
version = perf[0];
headerlen = perf[1];
if (version < 0x40) {
recordlen = perf[3] + (perf[4] * perf[5]);
entries = perf[2];
pm->pwm_divisor = ROM16(perf[6]);
} else {
recordlen = perf[2] + (perf[3] * perf[4]);
entries = perf[5];
......@@ -216,7 +217,7 @@ nouveau_perf_init(struct drm_device *dev)
return;
}
perf = ROMPTR(bios, bios->data[bios->offset + 0x94]);
perf = ROMPTR(dev, bios->data[bios->offset + 0x94]);
if (!perf) {
NV_DEBUG(dev, "perf table pointer invalid\n");
return;
......@@ -283,7 +284,6 @@ nouveau_perf_init(struct drm_device *dev)
perflvl->memory = ROM16(entry[11]) * 1000;
else
perflvl->memory = ROM16(entry[11]) * 2000;
break;
case 0x25:
perflvl->fanspeed = entry[4];
......@@ -300,8 +300,8 @@ nouveau_perf_init(struct drm_device *dev)
perflvl->core = ROM16(entry[8]) * 1000;
perflvl->shader = ROM16(entry[10]) * 1000;
perflvl->memory = ROM16(entry[12]) * 1000;
/*XXX: confirm on 0x35 */
perflvl->unk05 = ROM16(entry[16]) * 1000;
perflvl->vdec = ROM16(entry[16]) * 1000;
perflvl->dom6 = ROM16(entry[20]) * 1000;
break;
case 0x40:
#define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -78,9 +78,10 @@ nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
void
nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
struct nouveau_mem *mem, dma_addr_t *list)
struct nouveau_mem *mem)
{
struct nouveau_vm *vm = vma->vm;
dma_addr_t *list = mem->pages;
int big = vma->node->type != vm->spg_shift;
u32 offset = vma->node->offset + (delta >> 12);
u32 bits = vma->node->type - 12;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment