提交 77145f1c 编写于 作者: B Ben Skeggs

drm/nouveau: port remainder of drm code, and rip out compat layer

v2: Ben Skeggs <bskeggs@redhat.com>
- fill in nouveau_pm.dev to prevent oops
- fix ppc issues (build + OF shadow)
Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 2094dd82
......@@ -145,47 +145,17 @@ nouveau-y += core/engine/software/nv50.o
nouveau-y += core/engine/software/nvc0.o
nouveau-y += core/engine/vp/nv84.o
# drm/compat - will go away
nouveau-y += nouveau_compat.o nouveau_revcompat.o
# drm/core
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
nouveau-y += nouveau_agp.o
nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
nouveau-y += nouveau_abi16.o
nouveau-y += nouveau_prime.o nouveau_abi16.o
nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o
# drm/kms/common
nouveau-y += nouveau_fbcon.o
# drm/kms/nv04:nv50
nouveau-y += nv04_fbcon.o
# drm/kms/nv50:nvd9
nouveau-y += nv50_fbcon.o nvc0_fbcon.o
# drm/kms/nvd9-
# other random bits
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
nouveau-$(CONFIG_ACPI) += nouveau_acpi.o
nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
##
## unported bits below
##
# drm/core
nouveau-y += nouveau_drv.o nouveau_state.o nouveau_irq.o
nouveau-y += nouveau_prime.o
# drm/kms/bios
nouveau-y += nouveau_bios.o
# drm/kms/common
nouveau-y += nouveau_display.o nouveau_connector.o
nouveau-y += nouveau_hdmi.o nouveau_dp.o
# drm/kms
nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o
nouveau-y += nouveau_connector.o nouveau_hdmi.o nouveau_dp.o
nouveau-y += nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o
# drm/kms/nv04:nv50
nouveau-y += nouveau_hw.o nouveau_calc.o
......@@ -202,4 +172,9 @@ nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o
nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o
nouveau-y += nouveau_mem.o
# other random bits
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
nouveau-$(CONFIG_ACPI) += nouveau_acpi.o
nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o
obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
......@@ -20,8 +20,8 @@ void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *);
nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v))
#define nv_wait_ne(o,a,m,v) \
nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v))
#define nv_wait_cb(o,a,m,v) \
nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (a), (m), (v))
#define nv_wait_cb(o,c,d) \
nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (c), (d))
struct nouveau_timer {
struct nouveau_subdev base;
......
......@@ -56,6 +56,31 @@ nvbios_findstr(const u8 *data, int size, const char *str, int len)
return 0;
}
#if defined(__powerpc__)
static void
nouveau_bios_shadow_of(struct nouveau_bios *bios)
{
struct pci_dev *pdev = nv_device(bios)->pdev;
struct device_node *dn;
const u32 *data;
int size, i;
dn = pci_device_to_OF_node(pdev);
if (!dn) {
nv_info(bios, "Unable to get the OF node\n");
return;
}
data = of_get_property(dn, "NVDA,BMP", &size);
if (data) {
bios->size = size;
bios->data = kmalloc(bios->size, GFP_KERNEL);
if (bios->data)
memcpy(bios->data, data, size);
}
}
#endif
static void
nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
{
......@@ -221,7 +246,7 @@ nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
}
struct methods {
const char desc[8];
const char desc[16];
void (*shadow)(struct nouveau_bios *);
const bool rw;
int score;
......@@ -233,6 +258,9 @@ static int
nouveau_bios_shadow(struct nouveau_bios *bios)
{
struct methods shadow_methods[] = {
#if defined(__powerpc__)
{ "OpenFirmware", nouveau_bios_shadow_of, true, 0, 0, NULL },
#endif
{ "PRAMIN", nouveau_bios_shadow_pramin, true, 0, 0, NULL },
{ "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL },
{ "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL },
......
......@@ -71,7 +71,7 @@ static const struct backlight_ops nv40_bl_ops = {
static int
nv40_backlight_init(struct drm_connector *connector)
{
struct nouveau_drm *drm = nouveau_newpriv(connector->dev);
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nouveau_device *device = nv_device(drm->device);
struct backlight_properties props;
struct backlight_device *bd;
......@@ -95,7 +95,7 @@ static int
nv50_get_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nouveau_device *device = nv_device(drm->device);
int or = nv_encoder->or;
u32 div = 1025;
......@@ -110,7 +110,7 @@ static int
nv50_set_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nouveau_device *device = nv_device(drm->device);
int or = nv_encoder->or;
u32 div = 1025;
......@@ -131,7 +131,7 @@ static int
nva3_get_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nouveau_device *device = nv_device(drm->device);
int or = nv_encoder->or;
u32 div, val;
......@@ -149,7 +149,7 @@ static int
nva3_set_intensity(struct backlight_device *bd)
{
struct nouveau_encoder *nv_encoder = bl_get_data(bd);
struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev);
struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nouveau_device *device = nv_device(drm->device);
int or = nv_encoder->or;
u32 div, val;
......@@ -175,7 +175,7 @@ static const struct backlight_ops nva3_bl_ops = {
static int
nv50_backlight_init(struct drm_connector *connector)
{
struct nouveau_drm *drm = nouveau_newpriv(connector->dev);
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nouveau_device *device = nv_device(drm->device);
struct nouveau_encoder *nv_encoder;
struct backlight_properties props;
......@@ -216,7 +216,7 @@ nv50_backlight_init(struct drm_connector *connector)
int
nouveau_backlight_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_device *device = nv_device(drm->device);
struct drm_connector *connector;
......@@ -250,7 +250,7 @@ nouveau_backlight_init(struct drm_device *dev)
void
nouveau_backlight_exit(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
if (drm->backlight) {
backlight_device_unregister(drm->backlight);
......
......@@ -21,8 +21,8 @@
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __NOUVEAU_BIOS_H__
#define __NOUVEAU_BIOS_H__
#ifndef __NOUVEAU_DISPBIOS_H__
#define __NOUVEAU_DISPBIOS_H__
#include "nvreg.h"
......@@ -38,8 +38,8 @@
#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 nouveau_drm *drm = nouveau_drm((d)); \
ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \
})
struct bit_entry {
......@@ -180,4 +180,21 @@ int olddcb_outp_foreach(struct drm_device *, void *data,
u8 *olddcb_conntab(struct drm_device *);
u8 *olddcb_conn(struct drm_device *, u8 idx);
int nouveau_bios_init(struct drm_device *);
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,
bool *dl, bool *if_is_24bit);
int run_tmds_table(struct drm_device *, struct dcb_output *,
int head, int pxclk);
int call_lvds_script(struct drm_device *, struct dcb_output *, int head,
enum LVDS_script, int pxclk);
bool bios_encoder_match(struct dcb_output *, u32 hash);
#endif
......@@ -49,7 +49,7 @@ static void
nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg,
u32 addr, u32 size, u32 pitch, u32 flags)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
int i = reg - drm->tile.reg;
struct nouveau_fb *pfb = nouveau_fb(drm->device);
struct nouveau_fb_tile *tile = &pfb->tile.region[i];
......@@ -74,7 +74,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg,
static struct nouveau_drm_tile *
nv10_bo_get_tile_region(struct drm_device *dev, int i)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_drm_tile *tile = &drm->tile.reg[i];
spin_lock(&drm->tile.lock);
......@@ -93,7 +93,7 @@ static void
nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,
struct nouveau_fence *fence)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
if (tile) {
spin_lock(&drm->tile.lock);
......@@ -112,7 +112,7 @@ static struct nouveau_drm_tile *
nv10_bo_set_tiling(struct drm_device *dev, u32 addr,
u32 size, u32 pitch, u32 flags)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
struct nouveau_drm_tile *tile, *found = NULL;
int i;
......@@ -191,7 +191,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
struct sg_table *sg,
struct nouveau_bo **pnvbo)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_bo *nvbo;
size_t acc_size;
int ret;
......
......@@ -22,7 +22,8 @@
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"
#include "nouveau_reg.h"
#include "nouveau_hw.h"
/****************************************************************************\
......@@ -195,12 +196,13 @@ static void
nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
int *burst, int *lwm)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_device *device = nouveau_dev(dev);
struct nv_fifo_info fifo_data;
struct nv_sim_state sim_data;
int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY);
int NVClk = nouveau_hw_get_clock(dev, PLL_CORE);
uint32_t cfg1 = nv_rd32(dev, NV04_PFB_CFG1);
uint32_t cfg1 = nv_rd32(device, NV04_PFB_CFG1);
sim_data.pclk_khz = VClk;
sim_data.mclk_khz = MClk;
......@@ -218,13 +220,13 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
sim_data.mem_latency = 3;
sim_data.mem_page_miss = 10;
} else {
sim_data.memory_type = nv_rd32(dev, NV04_PFB_CFG0) & 0x1;
sim_data.memory_width = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
sim_data.memory_type = nv_rd32(device, NV04_PFB_CFG0) & 0x1;
sim_data.memory_width = (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
sim_data.mem_latency = cfg1 & 0xf;
sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
}
if (dev_priv->card_type == NV_04)
if (nv_device(drm->device)->card_type == NV_04)
nv04_calc_arb(&fifo_data, &sim_data);
else
nv10_calc_arb(&fifo_data, &sim_data);
......@@ -249,9 +251,9 @@ nv20_update_arb(int *burst, int *lwm)
void
nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
if (dev_priv->card_type < NV_20)
if (nv_device(drm->device)->card_type < NV_20)
nv04_update_arb(dev, vclk, bpp, burst, lwm);
else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ ||
(dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) {
......
#include "nouveau_drm.h"
#include "nouveau_chan.h"
#include "nouveau_compat.h"
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
#include <subdev/bios/init.h>
#include <subdev/bios/pll.h>
#include <subdev/gpio.h>
#include <subdev/i2c.h>
#include <subdev/clock.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
#include <subdev/bar.h>
#include <subdev/vm.h>
int
nvdrm_gart_init(struct drm_device *dev, u64 *base, u64 *size)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
if (drm->agp.stat == ENABLED) {
*base = drm->agp.base;
*size = drm->agp.base;
return 0;
}
return -ENODEV;
}
u8
_nv_rd08(struct drm_device *dev, u32 reg)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nv_ro08(drm->device, reg);
}
void
_nv_wr08(struct drm_device *dev, u32 reg, u8 val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
nv_wo08(drm->device, reg, val);
}
u32
_nv_rd32(struct drm_device *dev, u32 reg)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nv_ro32(drm->device, reg);
}
void
_nv_wr32(struct drm_device *dev, u32 reg, u32 val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
nv_wo32(drm->device, reg, val);
}
u32
_nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val)
{
u32 tmp = _nv_rd32(dev, reg);
_nv_wr32(dev, reg, (tmp & ~mask) | val);
return tmp;
}
bool
_nv_bios(struct drm_device *dev, u8 **data, u32 *size)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_bios *bios = nouveau_bios(drm->device);
*data = bios->data;
*size = bios->size;
return true;
}
void
nouveau_gpio_reset(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
gpio->reset(gpio);
}
int
nouveau_gpio_find(struct drm_device *dev, int idx, u8 tag, u8 line,
struct dcb_gpio_func *func)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
return gpio->find(gpio, idx, tag, line, func);
}
bool
nouveau_gpio_func_valid(struct drm_device *dev, u8 tag)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
struct dcb_gpio_func func;
return gpio->find(gpio, 0, tag, 0xff, &func) == 0;
}
int
nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
if (gpio && gpio->get)
return gpio->set(gpio, 0, tag, 0xff, state);
return -ENODEV;
}
int
nouveau_gpio_func_get(struct drm_device *dev, u8 tag)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
if (gpio && gpio->get)
return gpio->get(gpio, 0, tag, 0xff);
return -ENODEV;
}
int
nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
if (gpio && gpio->irq)
return gpio->irq(gpio, idx, tag, line, on);
return -ENODEV;
}
int
nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line,
void (*exec)(void *, int state), void *data)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
if (gpio && gpio->isr_add)
return gpio->isr_add(gpio, idx, tag, line, exec, data);
return -ENODEV;
}
void
nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line,
void (*exec)(void *, int state), void *data)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
if (gpio && gpio->isr_del)
gpio->isr_del(gpio, idx, tag, line, exec, data);
}
struct nouveau_i2c_port *
nouveau_i2c_find(struct drm_device *dev, u8 index)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
return i2c->find(i2c, index);
}
bool
nouveau_probe_i2c_addr(struct nouveau_i2c_port *port, int addr)
{
return nv_probe_i2c(port, addr);
}
struct i2c_adapter *
nouveau_i2c_adapter(struct nouveau_i2c_port *port)
{
return &port->adapter;
}
int
nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info,
bool (*match)(struct nouveau_i2c_port *,
struct i2c_board_info *),
int index)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
return i2c->identify(i2c, index, what, info, match);
}
int
auxch_rd(struct drm_device *dev, struct nouveau_i2c_port *port,
u32 addr, u8 *data, u8 size)
{
return nv_rdaux(port, addr, data, size);
}
int
auxch_wr(struct drm_device *dev, struct nouveau_i2c_port *port,
u32 addr, u8 *data, u8 size)
{
return nv_wraux(port, addr, data, size);
}
u32
get_pll_register(struct drm_device *dev, u32 type)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_bios *bios = nouveau_bios(drm->device);
struct nvbios_pll info;
if (nvbios_pll_parse(bios, type, &info))
return 0;
return info.reg;
}
int
get_pll_limits(struct drm_device *dev, u32 type, struct nvbios_pll *info)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_bios *bios = nouveau_bios(drm->device);
return nvbios_pll_parse(bios, type, info);
}
int
setPLL(struct drm_device *dev, u32 reg, u32 freq)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_clock *clk = nouveau_clock(drm->device);
int ret = -ENODEV;
if (clk->pll_set)
ret = clk->pll_set(clk, reg, freq);
return ret;
}
int
nouveau_calc_pll_mnp(struct drm_device *dev, struct nvbios_pll *info,
int freq, struct nouveau_pll_vals *pv)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_clock *clk = nouveau_clock(drm->device);
int ret = 0;
if (clk->pll_calc)
ret = clk->pll_calc(clk, info, freq, pv);
return ret;
}
int
nouveau_hw_setpll(struct drm_device *dev, u32 reg1,
struct nouveau_pll_vals *pv)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_clock *clk = nouveau_clock(drm->device);
int ret = -ENODEV;
if (clk->pll_prog)
ret = clk->pll_prog(clk, reg1, pv);
return ret;
}
int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq,
int *N, int *fN, int *M, int *P);
int
nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq,
int *N, int *fN, int *M, int *P)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_clock *clk = nouveau_clock(drm->device);
return nva3_pll_calc(clk, info, freq, N, fN, M, P);
}
void
nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
struct dcb_output *dcbent, int crtc)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_bios *bios = nouveau_bios(drm->device);
struct nvbios_init init = {
.subdev = nv_subdev(bios),
.bios = bios,
.offset = table,
.outp = dcbent,
.crtc = crtc,
.execute = 1
};
nvbios_exec(&init);
}
void
nouveau_bios_init_exec(struct drm_device *dev, uint16_t table)
{
nouveau_bios_run_init_table(dev, table, NULL, 0);
}
void
nv_intr(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_mc *pmc = nouveau_mc(drm->device);
nv_subdev(pmc)->intr(&pmc->base);
}
bool nouveau_wait_eq(struct drm_device *dev, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_timer_wait_eq(drm->device, timeout, reg, mask, val);
}
bool nouveau_wait_ne(struct drm_device *dev, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_timer_wait_ne(drm->device, timeout, reg, mask, val);
}
bool nouveau_wait_cb(struct drm_device *dev, u64 timeout,
bool (*cond)(void *), void *data)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_timer_wait_cb(drm->device, timeout, cond, data);
}
u64
nv_timer_read(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_timer *ptimer = nouveau_timer(drm->device);
return ptimer->read(ptimer);
}
int
nvfb_tile_nr(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return pfb->tile.regions;
}
struct nouveau_fb_tile *
nvfb_tile(struct drm_device *dev, int i)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return &pfb->tile.region[i];
}
void
nvfb_tile_init(struct drm_device *dev, int i, u32 a, u32 b, u32 c, u32 d)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
pfb->tile.init(pfb, i, a, b, c, d, &pfb->tile.region[i]);
}
void
nvfb_tile_fini(struct drm_device *dev, int i)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
pfb->tile.fini(pfb, i, &pfb->tile.region[i]);
}
void
nvfb_tile_prog(struct drm_device *dev, int i)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
pfb->tile.prog(pfb, i, &pfb->tile.region[i]);
}
bool
nvfb_flags_valid(struct drm_device *dev, u32 flags)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return pfb->memtype_valid(pfb, flags);
}
int
nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
u32 memtype, struct nouveau_mem **pmem)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
int ret = pfb->ram.get(pfb, size, align, ncmin, memtype, pmem);
if (ret)
return ret;
(*pmem)->dev = dev;
return 0;
}
void
nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
pfb->ram.put(pfb, pmem);
}
u64 nvfb_vram_sys_base(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return pfb->ram.stolen;
}
u64 nvfb_vram_size(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return pfb->ram.size;
}
int nvfb_vram_type(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return pfb->ram.type;
}
int nvfb_vram_rank_B(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
return pfb->ram.ranks > 1;
}
void
nv50_fb_vm_trap(struct drm_device *dev, int disp)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
nv50_fb_trap(nouveau_fb(drm->device), disp);
}
#include <core/subdev/instmem/nv04.h>
struct nouveau_gpuobj *
nvimem_ramro(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nv04_instmem_priv *imem = (void *)nouveau_instmem(drm->device);
return imem->ramro;
}
struct nouveau_gpuobj *
nvimem_ramfc(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nv04_instmem_priv *imem = (void *)nouveau_instmem(drm->device);
return imem->ramfc;
}
int _nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_gpuobj *par,
int size, int align, u32 flags,
struct nouveau_gpuobj **pobj)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
int ret;
if (!par)
flags |= NVOBJ_FLAG_HEAP;
ret = nouveau_gpuobj_new(drm->device, nv_object(par), size, align,
flags, pobj);
if (ret)
return ret;
(*pobj)->dev = dev;
return 0;
}
u32 nv_ri32(struct drm_device *dev , u32 addr)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_instmem *imem = nouveau_instmem(drm->device);
return nv_ro32(imem, addr);
}
void nv_wi32(struct drm_device *dev, u32 addr, u32 data)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_instmem *imem = nouveau_instmem(drm->device);
nv_wo32(imem, addr, data);
}
u32 nvimem_reserved(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_instmem *imem = nouveau_instmem(drm->device);
return imem->reserved;
}
int
nvbar_map(struct drm_device *dev, struct nouveau_mem *mem, u32 flags,
struct nouveau_vma *vma)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_bar *bar = nouveau_bar(drm->device);
return bar->umap(bar, mem, flags, vma);
}
void
nvbar_unmap(struct drm_device *dev, struct nouveau_vma *vma)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_bar *bar = nouveau_bar(drm->device);
bar->unmap(bar, vma);
}
int
nouveau_gpuobj_map_bar(struct nouveau_gpuobj *gpuobj, u32 flags,
struct nouveau_vma *vma)
{
struct nouveau_drm *drm = nouveau_newpriv(gpuobj->dev);
struct nouveau_bar *bar = nouveau_bar(drm->device);
struct nouveau_instobj *iobj = (void *)
nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS);
struct nouveau_mem **mem = (void *)(iobj + 1);
struct nouveau_mem *node = *mem;
return bar->umap(bar, node, flags, vma);
}
void
nvimem_flush(struct drm_device *dev)
{
}
void _nv50_vm_flush_engine(struct drm_device *dev, int engine)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
nv50_vm_flush_engine(nv_subdev(drm->device), engine);
}
int _nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length,
u64 mm_offset, struct nouveau_vm **pvm)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return nouveau_vm_new(nv_device(drm->device), offset, length, mm_offset, pvm);
}
#include <core/subdev/vm/nv04.h>
struct nouveau_vm *
nv04vm_ref(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device);
struct nv04_vmmgr_priv *priv = (void *)vmm;
return priv->vm;
}
struct nouveau_gpuobj *
nv04vm_refdma(struct drm_device *dev)
{
struct nouveau_gpuobj *gpuobj = NULL;
nouveau_gpuobj_ref(nv04vm_ref(dev)->pgt[0].obj[0], &gpuobj);
return gpuobj;
}
void
nvvm_engref(struct nouveau_vm *vm, int eng, int ref)
{
atomic_add(ref, &vm->engref[eng]);
}
int
nvvm_spg_shift(struct nouveau_vm *vm)
{
return vm->vmm->spg_shift;
}
int
nvvm_lpg_shift(struct nouveau_vm *vm)
{
return vm->vmm->lpg_shift;
}
u64 nvgpuobj_addr(struct nouveau_object *object)
{
return nv_gpuobj(object)->addr;
}
struct drm_device *
nouveau_drv(void *ptr)
{
struct nouveau_drm *drm = ptr;
return drm->dev;
}
struct nouveau_channel *
nvdrm_channel(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
return drm->channel;
}
struct mutex *
nvchan_mutex(struct nouveau_channel *chan)
{
return &chan->cli->mutex;
}
#ifndef __NOUVEAU_COMPAT_H__
#define __NOUVEAU_COMPAT_H__
int nvdrm_gart_init(struct drm_device *, u64 *, u64 *);
u8 _nv_rd08(struct drm_device *, u32);
void _nv_wr08(struct drm_device *, u32, u8);
u32 _nv_rd32(struct drm_device *, u32);
void _nv_wr32(struct drm_device *, u32, u32);
u32 _nv_mask(struct drm_device *, u32, u32, u32);
bool _nv_bios(struct drm_device *, u8 **, u32 *);
struct dcb_gpio_func;
void nouveau_gpio_reset(struct drm_device *);
int nouveau_gpio_find(struct drm_device *, int, u8, u8, struct dcb_gpio_func *);
bool nouveau_gpio_func_valid(struct drm_device *, u8 tag);
int nouveau_gpio_func_set(struct drm_device *, u8 tag, int state);
int nouveau_gpio_func_get(struct drm_device *, u8 tag);
int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on);
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);
struct nouveau_i2c_port *nouveau_i2c_find(struct drm_device *, u8);
bool nouveau_probe_i2c_addr(struct nouveau_i2c_port *, int addr);
struct i2c_adapter *nouveau_i2c_adapter(struct nouveau_i2c_port *);
int nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info,
bool (*match)(struct nouveau_i2c_port *,
struct i2c_board_info *), int index);
int auxch_rd(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8);
int auxch_wr(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8);
struct nvbios_pll;
struct nouveau_pll_vals;
u32 get_pll_register(struct drm_device *dev, u32 type);
int get_pll_limits(struct drm_device *, u32, struct nvbios_pll *);
int setPLL(struct drm_device *, u32 reg, u32 clk);
int nouveau_calc_pll_mnp(struct drm_device *, struct nvbios_pll *,
int, struct nouveau_pll_vals *);
int nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq,
int *N, int *fN, int *M, int *P);
int nouveau_hw_setpll(struct drm_device *, u32, struct nouveau_pll_vals *);
struct dcb_output;
void nouveau_bios_run_init_table(struct drm_device *, u16, struct dcb_output *, int);
void nouveau_bios_init_exec(struct drm_device *, u16);
void nv_intr(struct drm_device *);
bool nouveau_wait_eq(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
bool nouveau_wait_ne(struct drm_device *, uint64_t timeout,
uint32_t reg, uint32_t mask, uint32_t val);
bool nouveau_wait_cb(struct drm_device *, u64 timeout,
bool (*cond)(void *), void *);
u64 nv_timer_read(struct drm_device *);
int nvfb_tile_nr(struct drm_device *);
void nvfb_tile_init(struct drm_device *, int, u32, u32, u32, u32);
void nvfb_tile_fini(struct drm_device *, int);
void nvfb_tile_prog(struct drm_device *, int);
struct nouveau_fb_tile *nvfb_tile(struct drm_device *, int);
struct nouveau_mem;
int nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
u32 memtype, struct nouveau_mem **pmem);
void nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem);
bool nvfb_flags_valid(struct drm_device *dev, u32);
u64 nvfb_vram_sys_base(struct drm_device *);
u64 nvfb_vram_size(struct drm_device *);
int nvfb_vram_type(struct drm_device *);
int nvfb_vram_rank_B(struct drm_device *);
void nv50_fb_vm_trap(struct drm_device *, int);
struct nouveau_gpuobj *nvimem_ramro(struct drm_device *);
struct nouveau_gpuobj *nvimem_ramfc(struct drm_device *);
int _nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_gpuobj *par,
int size, int align, u32 flags,
struct nouveau_gpuobj **pboj);
u32 nv_ri32(struct drm_device *, u32);
void nv_wi32(struct drm_device *, u32, u32);
u32 nvimem_reserved(struct drm_device *);
void nvimem_flush(struct drm_device *);
void _nv50_vm_flush_engine(struct drm_device *dev, int engine);
int _nouveau_vm_new(struct drm_device *, u64 offset, u64 length,
u64 mm_offset, struct nouveau_vm **);
struct nouveau_vma;
int nouveau_gpuobj_map_bar(struct nouveau_gpuobj *, u32, struct nouveau_vma *);
int
nvbar_map(struct drm_device *dev, struct nouveau_mem *mem, u32 flags,
struct nouveau_vma *vma);
void
nvbar_unmap(struct drm_device *dev, struct nouveau_vma *vma);
struct nouveau_vm *
nv04vm_ref(struct drm_device *dev);
struct nouveau_gpuobj *
nv04vm_refdma(struct drm_device *dev);
void
nvvm_engref(struct nouveau_vm *, int, int);
int
nvvm_spg_shift(struct nouveau_vm *);
int
nvvm_lpg_shift(struct nouveau_vm *);
u32
nv50_display_active_crtcs(struct drm_device *dev);
u64 nvgpuobj_addr(struct nouveau_object *object);
struct drm_device *
nouveau_drv(void *drm);
struct nouveau_channel *
nvdrm_channel(struct drm_device *dev);
struct mutex *
nvchan_mutex(struct nouveau_channel *chan);
#endif
......@@ -31,14 +31,29 @@
#include "drm_crtc_helper.h"
#include "nouveau_reg.h"
#include "nouveau_drv.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include "nouveau_connector.h"
#include "nouveau_drm.h"
#include "nouveau_hw.h"
#include "nouveau_acpi.h"
#include <subdev/bios/gpio.h>
#include "nouveau_display.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include <subdev/i2c.h>
#include <subdev/gpio.h>
MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
static int nouveau_tv_disable = 0;
module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
static int nouveau_ignorelid = 0;
module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)");
static int nouveau_duallink = 1;
module_param_named(duallink, nouveau_duallink, int, 0400);
static void nouveau_connector_hotplug(void *, int);
......@@ -85,19 +100,21 @@ static void
nouveau_connector_destroy(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct drm_nouveau_private *dev_priv;
struct nouveau_gpio *gpio;
struct nouveau_drm *drm;
struct drm_device *dev;
if (!nv_connector)
return;
dev = nv_connector->base.dev;
dev_priv = dev->dev_private;
NV_DEBUG_KMS(dev, "\n");
dev = nv_connector->base.dev;
drm = nouveau_drm(dev);
gpio = nouveau_gpio(drm->device);
NV_DEBUG(drm, "\n");
if (nv_connector->hpd != DCB_GPIO_UNUSED) {
nouveau_gpio_isr_del(dev, 0, nv_connector->hpd, 0xff,
nouveau_connector_hotplug, connector);
if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) {
gpio->isr_del(gpio, 0, nv_connector->hpd, 0xff,
nouveau_connector_hotplug, connector);
}
kfree(nv_connector->edid);
......@@ -111,10 +128,12 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
struct nouveau_encoder **pnv_encoder)
{
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
struct nouveau_i2c_port *i2c = NULL;
struct nouveau_i2c_port *port = NULL;
struct nouveau_encoder *nv_encoder;
struct drm_mode_object *obj;
int id;
......@@ -129,11 +148,10 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
nv_encoder = nouveau_encoder(obj_to_encoder(obj));
if (nv_encoder->dcb->i2c_index < 0xf)
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
port = i2c->find(i2c, nv_encoder->dcb->i2c_index);
if (port && nv_probe_i2c(port, 0x50)) {
*pnv_encoder = nv_encoder;
return i2c;
return port;
}
}
......@@ -175,14 +193,14 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
struct nouveau_encoder *nv_encoder)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct drm_device *dev = connector->dev;
if (nv_connector->detected_encoder == nv_encoder)
return;
nv_connector->detected_encoder = nv_encoder;
if (dev_priv->card_type >= NV_50) {
if (nv_device(drm->device)->card_type >= NV_50) {
connector->interlace_allowed = true;
connector->doublescan_allowed = true;
} else
......@@ -192,8 +210,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
connector->interlace_allowed = false;
} else {
connector->doublescan_allowed = true;
if (dev_priv->card_type == NV_20 ||
(dev_priv->card_type == NV_10 &&
if (nv_device(drm->device)->card_type == NV_20 ||
(nv_device(drm->device)->card_type == NV_10 &&
(dev->pci_device & 0x0ff0) != 0x0100 &&
(dev->pci_device & 0x0ff0) != 0x0150))
/* HW is broken */
......@@ -215,6 +233,7 @@ static enum drm_connector_status
nouveau_connector_detect(struct drm_connector *connector, bool force)
{
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL;
struct nouveau_encoder *nv_partner;
......@@ -230,18 +249,18 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
if (i2c) {
nv_connector->edid = drm_get_edid(connector, nouveau_i2c_adapter(i2c));
nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
drm_mode_connector_update_edid_property(connector,
nv_connector->edid);
if (!nv_connector->edid) {
NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
NV_ERROR(drm, "DDC responded, but no EDID for %s\n",
drm_get_connector_name(connector));
goto detect_analog;
}
if (nv_encoder->dcb->type == DCB_OUTPUT_DP &&
!nouveau_dp_detect(to_drm_encoder(nv_encoder))) {
NV_ERROR(dev, "Detected %s, but failed init\n",
NV_ERROR(drm, "Detected %s, but failed init\n",
drm_get_connector_name(connector));
return connector_status_disconnected;
}
......@@ -303,7 +322,7 @@ static enum drm_connector_status
nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
{
struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL;
enum drm_connector_status status = connector_status_disconnected;
......@@ -320,7 +339,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
return connector_status_disconnected;
/* Try retrieving EDID via DDC */
if (!dev_priv->vbios.fp_no_ddc) {
if (!drm->vbios.fp_no_ddc) {
status = nouveau_connector_detect(connector, force);
if (status == connector_status_connected)
goto out;
......@@ -346,7 +365,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
* modeline is avalilable for the panel, set it as the panel's
* native mode and exit.
*/
if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc ||
if (nouveau_bios_fp_mode(dev, NULL) && (drm->vbios.fp_no_ddc ||
nv_encoder->dcb->lvdsconf.use_straps_for_mode)) {
status = connector_status_connected;
goto out;
......@@ -355,7 +374,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
/* Still nothing, some VBIOS images have a hardcoded EDID block
* stored for the panel stored in them.
*/
if (!dev_priv->vbios.fp_no_ddc) {
if (!drm->vbios.fp_no_ddc) {
struct edid *edid =
(struct edid *)nouveau_bios_embedded_edid(dev);
if (edid) {
......@@ -381,6 +400,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
static void
nouveau_connector_force(struct drm_connector *connector)
{
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder;
int type;
......@@ -395,7 +415,7 @@ nouveau_connector_force(struct drm_connector *connector)
nv_encoder = find_encoder(connector, type);
if (!nv_encoder) {
NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
NV_ERROR(drm, "can't find encoder to force %s on!\n",
drm_get_connector_name(connector));
connector->status = connector_status_disconnected;
return;
......@@ -408,8 +428,7 @@ static int
nouveau_connector_set_property(struct drm_connector *connector,
struct drm_property *property, uint64_t value)
{
struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
struct nouveau_display_engine *disp = &dev_priv->engine.display;
struct nouveau_display *disp = nouveau_display(connector->dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
......@@ -545,6 +564,7 @@ static struct drm_display_mode *
nouveau_connector_native_mode(struct drm_connector *connector)
{
struct drm_connector_helper_funcs *helper = connector->helper_private;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode, *largest = NULL;
......@@ -558,7 +578,7 @@ nouveau_connector_native_mode(struct drm_connector *connector)
/* Use preferred mode if there is one.. */
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
NV_DEBUG_KMS(dev, "native mode from preferred\n");
NV_DEBUG(drm, "native mode from preferred\n");
return drm_mode_duplicate(dev, mode);
}
......@@ -581,7 +601,7 @@ nouveau_connector_native_mode(struct drm_connector *connector)
largest = mode;
}
NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n",
NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
high_w, high_h, high_v);
return largest ? drm_mode_duplicate(dev, largest) : NULL;
}
......@@ -645,10 +665,10 @@ nouveau_connector_scaler_modes_add(struct drm_connector *connector)
static void
nouveau_connector_detect_depth(struct drm_connector *connector)
{
struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
struct nvbios *bios = &dev_priv->vbios;
struct nvbios *bios = &drm->vbios;
struct drm_display_mode *mode = nv_connector->native_mode;
bool duallink;
......@@ -695,7 +715,7 @@ static int
nouveau_connector_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
......@@ -713,7 +733,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
else
if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS &&
(nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
struct drm_display_mode mode;
nouveau_bios_fp_mode(dev, &mode);
......@@ -763,15 +783,15 @@ static unsigned
get_tmds_link_bandwidth(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
if (dcb->location != DCB_LOC_ON_CHIP ||
dev_priv->chipset >= 0x46)
nv_device(drm->device)->chipset >= 0x46)
return 165000;
else if (dev_priv->chipset >= 0x40)
else if (nv_device(drm->device)->chipset >= 0x40)
return 155000;
else if (dev_priv->chipset >= 0x18)
else if (nv_device(drm->device)->chipset >= 0x18)
return 135000;
else
return 112000;
......@@ -901,14 +921,15 @@ struct drm_connector *
nouveau_connector_create(struct drm_device *dev, int index)
{
const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_display_engine *disp = &dev_priv->engine.display;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_connector *nv_connector = NULL;
struct drm_connector *connector;
int type, ret = 0;
bool dummy;
NV_DEBUG_KMS(dev, "\n");
NV_DEBUG(drm, "\n");
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
nv_connector = nouveau_connector(connector);
......@@ -941,7 +962,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
nv_connector->type = nv_connector->dcb[0];
if (drm_conntype_from_dcb(nv_connector->type) ==
DRM_MODE_CONNECTOR_Unknown) {
NV_WARN(dev, "unknown connector type %02x\n",
NV_WARN(drm, "unknown connector type %02x\n",
nv_connector->type);
nv_connector->type = DCB_CONNECTOR_NONE;
}
......@@ -966,8 +987,8 @@ nouveau_connector_create(struct drm_device *dev, int index)
* figure out something suitable ourselves
*/
if (nv_connector->type == DCB_CONNECTOR_NONE) {
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_table *dcbt = &dev_priv->vbios.dcb;
struct nouveau_drm *drm = nouveau_drm(dev);
struct dcb_table *dcbt = &drm->vbios.dcb;
u32 encoders = 0;
int i;
......@@ -1003,7 +1024,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
if (type == DRM_MODE_CONNECTOR_LVDS) {
ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy);
if (ret) {
NV_ERROR(dev, "Error parsing LVDS table, disabling\n");
NV_ERROR(drm, "Error parsing LVDS table, disabling\n");
kfree(nv_connector);
return ERR_PTR(ret);
}
......@@ -1053,7 +1074,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
switch (nv_connector->type) {
case DCB_CONNECTOR_VGA:
if (dev_priv->card_type >= NV_50) {
if (nv_device(drm->device)->card_type >= NV_50) {
drm_connector_attach_property(connector,
dev->mode_config.scaling_mode_property,
nv_connector->scaling_mode);
......@@ -1086,10 +1107,9 @@ nouveau_connector_create(struct drm_device *dev, int index)
}
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
if (nv_connector->hpd != DCB_GPIO_UNUSED) {
ret = nouveau_gpio_isr_add(dev, 0, nv_connector->hpd, 0xff,
nouveau_connector_hotplug,
connector);
if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) {
ret = gpio->isr_add(gpio, 0, nv_connector->hpd, 0xff,
nouveau_connector_hotplug, connector);
if (ret == 0)
connector->polled = DRM_CONNECTOR_POLL_HPD;
}
......@@ -1103,8 +1123,9 @@ nouveau_connector_hotplug(void *data, int plugged)
{
struct drm_connector *connector = data;
struct drm_device *dev = connector->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un",
NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un",
drm_get_connector_name(connector));
if (plugged)
......
......@@ -26,18 +26,20 @@
#include "drmP.h"
#include "drm_crtc_helper.h"
#include "nouveau_drv.h"
#include "nouveau_fb.h"
#include "nouveau_fbcon.h"
#include "nouveau_hw.h"
#include "nouveau_crtc.h"
#include "nouveau_dma.h"
#include "nouveau_gem.h"
#include "nouveau_connector.h"
#include "nv50_display.h"
#include "nouveau_fence.h"
#include <subdev/bios/gpio.h>
#include <subdev/gpio.h>
#include <engine/disp.h>
static void
nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
......@@ -72,7 +74,7 @@ nouveau_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct nouveau_bo *nvbo)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_framebuffer *fb = &nv_fb->base;
int ret;
......@@ -84,7 +86,7 @@ nouveau_framebuffer_init(struct drm_device *dev,
drm_helper_mode_fill_fb_struct(fb, mode_cmd);
nv_fb->nvbo = nvbo;
if (dev_priv->card_type >= NV_50) {
if (nv_device(drm->device)->card_type >= NV_50) {
u32 tile_flags = nouveau_bo_tile_layout(nvbo);
if (tile_flags == 0x7a00 ||
tile_flags == 0xfe00)
......@@ -103,21 +105,21 @@ nouveau_framebuffer_init(struct drm_device *dev,
case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break;
case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break;
default:
NV_ERROR(dev, "unknown depth %d\n", fb->depth);
NV_ERROR(drm, "unknown depth %d\n", fb->depth);
return -EINVAL;
}
if (dev_priv->chipset == 0x50)
if (nv_device(drm->device)->chipset == 0x50)
nv_fb->r_format |= (tile_flags << 8);
if (!tile_flags) {
if (dev_priv->card_type < NV_D0)
if (nv_device(drm->device)->card_type < NV_D0)
nv_fb->r_pitch = 0x00100000 | fb->pitches[0];
else
nv_fb->r_pitch = 0x01000000 | fb->pitches[0];
} else {
u32 mode = nvbo->tile_mode;
if (dev_priv->card_type >= NV_C0)
if (nv_device(drm->device)->card_type >= NV_C0)
mode >>= 4;
nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode;
}
......@@ -213,8 +215,9 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {
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 nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
struct drm_connector *connector;
int ret;
......@@ -226,8 +229,8 @@ nouveau_display_init(struct drm_device *dev)
* some vbios default this to off for some reason, causing the
* panel to not work after resume
*/
if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) {
nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true);
if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) {
gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
msleep(300);
}
......@@ -237,7 +240,8 @@ nouveau_display_init(struct drm_device *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);
if (gpio)
gpio->irq(gpio, 0, conn->hpd, 0xff, true);
}
return ret;
......@@ -246,14 +250,16 @@ nouveau_display_init(struct drm_device *dev)
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 nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
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);
if (gpio)
gpio->irq(gpio, 0, conn->hpd, 0xff, false);
}
drm_kms_helper_poll_disable(dev);
......@@ -281,18 +287,28 @@ nouveau_display_vblank_put(void *data, int crtc)
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;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
struct nouveau_display *disp;
int ret, gen;
disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
if (!disp)
return -ENOMEM;
pdisp->vblank.data = dev;
pdisp->vblank.notify = nouveau_display_vblank_notify;
pdisp->vblank.get = nouveau_display_vblank_get;
pdisp->vblank.put = nouveau_display_vblank_put;
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)
if (nv_device(drm->device)->card_type < NV_50)
gen = 0;
else
if (dev_priv->card_type < NV_D0)
if (nv_device(drm->device)->card_type < NV_D0)
gen = 1;
else
gen = 2;
......@@ -326,11 +342,11 @@ nouveau_display_create(struct drm_device *dev)
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
if (dev_priv->card_type < NV_10) {
if (nv_device(drm->device)->card_type < NV_10) {
dev->mode_config.max_width = 2048;
dev->mode_config.max_height = 2048;
} else
if (dev_priv->card_type < NV_50) {
if (nv_device(drm->device)->card_type < NV_50) {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
} else {
......@@ -344,7 +360,13 @@ nouveau_display_create(struct drm_device *dev)
drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev);
ret = disp->create(dev);
if (nv_device(drm->device)->card_type < NV_50)
ret = nv04_display_create(dev);
else
if (nv_device(drm->device)->card_type < NV_D0)
ret = nv50_display_create(dev);
else
ret = nvd0_display_create(dev);
if (ret)
goto disp_create_err;
......@@ -354,10 +376,11 @@ nouveau_display_create(struct drm_device *dev)
goto vblank_err;
}
nouveau_backlight_init(dev);
return 0;
vblank_err:
disp->destroy(dev);
disp->dtor(dev);
disp_create_err:
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
......@@ -367,28 +390,109 @@ nouveau_display_create(struct drm_device *dev)
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;
struct nouveau_display *disp = nouveau_display(dev);
nouveau_backlight_exit(dev);
drm_vblank_cleanup(dev);
disp->destroy(dev);
disp->dtor(dev);
drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev);
nouveau_drm(dev)->display = NULL;
kfree(disp);
}
int
nouveau_display_suspend(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_crtc *crtc;
nouveau_display_fini(dev);
NV_INFO(drm, "unpinning framebuffer(s)...\n");
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_framebuffer *nouveau_fb;
nouveau_fb = nouveau_framebuffer(crtc->fb);
if (!nouveau_fb || !nouveau_fb->nvbo)
continue;
nouveau_bo_unpin(nouveau_fb->nvbo);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
}
return 0;
}
void
nouveau_display_resume(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_crtc *crtc;
int ret;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_framebuffer *nouveau_fb;
nouveau_fb = nouveau_framebuffer(crtc->fb);
if (!nouveau_fb || !nouveau_fb->nvbo)
continue;
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
if (!ret)
ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
if (ret)
NV_ERROR(drm, "Could not pin/map cursor.\n");
}
nouveau_fbcon_set_suspend(dev, 0);
nouveau_fbcon_zfill_all(dev);
nouveau_display_init(dev);
/* Force CLUT to get re-loaded during modeset */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
nv_crtc->lut.depth = 0;
}
drm_helper_resume_force_mode(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;
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);
}
}
int
nouveau_vblank_enable(struct drm_device *dev, int crtc)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_device *device = nouveau_dev(dev);
if (dev_priv->card_type >= NV_D0)
nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 1);
if (device->card_type >= NV_D0)
nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1);
else
if (dev_priv->card_type >= NV_50)
nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
if (device->card_type >= NV_50)
nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0,
NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
else
NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
......@@ -400,13 +504,13 @@ nouveau_vblank_enable(struct drm_device *dev, int crtc)
void
nouveau_vblank_disable(struct drm_device *dev, int crtc)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_device *device = nouveau_dev(dev);
if (dev_priv->card_type >= NV_D0)
nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 0);
if (device->card_type >= NV_D0)
nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0);
else
if (dev_priv->card_type >= NV_50)
nv_mask(dev, NV50_PDISPLAY_INTR_EN_1,
if (device->card_type >= NV_50)
nv_mask(device, NV50_PDISPLAY_INTR_EN_1,
NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
else
NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
......@@ -461,8 +565,8 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
struct nouveau_fence **pfence)
{
struct nouveau_fence_chan *fctx = chan->fence;
struct drm_device *dev = nouveau_drv(chan->drm);
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = chan->drm;
struct drm_device *dev = drm->dev;
unsigned long flags;
int ret;
......@@ -481,7 +585,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
if (ret)
goto fail;
if (dev_priv->card_type < NV_C0) {
if (nv_device(drm->device)->card_type < NV_C0) {
BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
OUT_RING (chan, 0x00000000);
OUT_RING (chan, 0x00000000);
......@@ -509,7 +613,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event)
{
struct drm_device *dev = crtc->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
struct nouveau_page_flip_state *s;
......@@ -517,7 +621,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct nouveau_fence *fence;
int ret;
if (!nvdrm_channel(dev))
if (!drm->channel)
return -ENODEV;
s = kzalloc(sizeof(*s), GFP_KERNEL);
......@@ -540,23 +644,23 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
if (fence)
chan = fence->channel;
if (!chan)
chan = nvdrm_channel(dev);
mutex_lock(nvchan_mutex(chan));
chan = drm->channel;
mutex_lock(&chan->cli->mutex);
/* Emit a page flip */
if (dev_priv->card_type >= NV_50) {
if (dev_priv->card_type >= NV_D0)
if (nv_device(drm->device)->card_type >= NV_50) {
if (nv_device(drm->device)->card_type >= NV_D0)
ret = nvd0_display_flip_next(crtc, fb, chan, 0);
else
ret = nv50_display_flip_next(crtc, fb, chan);
if (ret) {
mutex_unlock(nvchan_mutex(chan));
mutex_unlock(&chan->cli->mutex);
goto fail_unreserve;
}
}
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
mutex_unlock(nvchan_mutex(chan));
mutex_unlock(&chan->cli->mutex);
if (ret)
goto fail_unreserve;
......@@ -579,14 +683,15 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
struct nouveau_page_flip_state *ps)
{
struct nouveau_fence_chan *fctx = chan->fence;
struct drm_device *dev = nouveau_drv(chan->drm);
struct nouveau_drm *drm = chan->drm;
struct drm_device *dev = drm->dev;
struct nouveau_page_flip_state *s;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (list_empty(&fctx->flip)) {
NV_ERROR(dev, "unexpected pageflip\n");
NV_ERROR(drm, "unexpected pageflip\n");
spin_unlock_irqrestore(&dev->event_lock, flags);
return -EINVAL;
}
......@@ -617,13 +722,12 @@ int
nouveau_flip_complete(void *data)
{
struct nouveau_channel *chan = data;
struct drm_device *dev = nouveau_drv(chan->drm);
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = chan->drm;
struct nouveau_page_flip_state state;
if (!nouveau_finish_page_flip(chan, &state)) {
if (dev_priv->card_type < NV_50) {
nv_set_crtc_base(dev, state.crtc, state.offset +
if (nv_device(drm->device)->card_type < NV_50) {
nv_set_crtc_base(drm->dev, state.crtc, state.offset +
state.y * state.pitch +
state.x * state.bpp / 8);
}
......
#ifndef __NOUVEAU_DISPLAY_H__
#define __NOUVEAU_DISPLAY_H__
#include <subdev/vm.h>
#include "nouveau_drm.h"
struct nouveau_framebuffer {
struct drm_framebuffer base;
struct nouveau_bo *nvbo;
struct nouveau_vma vma;
u32 r_dma;
u32 r_format;
u32 r_pitch;
};
static inline struct nouveau_framebuffer *
nouveau_framebuffer(struct drm_framebuffer *fb)
{
return container_of(fb, struct nouveau_framebuffer, base);
}
int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *,
struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
struct nouveau_page_flip_state {
struct list_head head;
struct drm_pending_vblank_event *event;
int crtc, bpp, pitch, x, y;
u64 offset;
};
struct nouveau_display {
void *priv;
void (*dtor)(struct drm_device *);
int (*init)(struct drm_device *);
void (*fini)(struct drm_device *);
struct drm_property *dithering_mode;
struct drm_property *dithering_depth;
struct drm_property *underscan_property;
struct drm_property *underscan_hborder_property;
struct drm_property *underscan_vborder_property;
/* not really hue and saturation: */
struct drm_property *vibrant_hue_property;
struct drm_property *color_vibrance_property;
};
static inline struct nouveau_display *
nouveau_display(struct drm_device *dev)
{
return nouveau_drm(dev)->display;
}
int nouveau_display_create(struct drm_device *dev);
void nouveau_display_destroy(struct drm_device *dev);
int nouveau_display_init(struct drm_device *dev);
void nouveau_display_fini(struct drm_device *dev);
int nouveau_display_suspend(struct drm_device *dev);
void nouveau_display_resume(struct drm_device *dev);
int nouveau_vblank_enable(struct drm_device *dev, int crtc);
void nouveau_vblank_disable(struct drm_device *dev, int crtc);
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event);
int nouveau_finish_page_flip(struct nouveau_channel *,
struct nouveau_page_flip_state *);
int nouveau_display_dumb_create(struct drm_file *, struct drm_device *,
struct drm_mode_create_dumb *args);
int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
u32 handle, u64 *offset);
int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *,
u32 handle);
void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
extern int nouveau_backlight_init(struct drm_device *);
extern void nouveau_backlight_exit(struct drm_device *);
#else
static inline int
nouveau_backlight_init(struct drm_device *dev)
{
return 0;
}
static inline void
nouveau_backlight_exit(struct drm_device *dev) {
}
#endif
#endif
......@@ -25,31 +25,35 @@
#include "drmP.h"
#include "drm_dp_helper.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include <subdev/gpio.h>
#include <subdev/i2c.h>
u8 *
nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct bit_entry d;
u8 *table;
int i;
if (bit_table(dev, 'd', &d)) {
NV_ERROR(dev, "BIT 'd' table not found\n");
NV_ERROR(drm, "BIT 'd' table not found\n");
return NULL;
}
if (d.version != 1) {
NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version);
NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version);
return NULL;
}
table = ROMPTR(dev, d.data[0]);
if (!table) {
NV_ERROR(dev, "displayport table pointer invalid\n");
NV_ERROR(drm, "displayport table pointer invalid\n");
return NULL;
}
......@@ -60,7 +64,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
case 0x40:
break;
default:
NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]);
NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]);
return NULL;
}
......@@ -70,7 +74,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry)
return table;
}
NV_ERROR(dev, "displayport encoder table not found\n");
NV_ERROR(drm, "displayport encoder table not found\n");
return NULL;
}
......@@ -92,9 +96,10 @@ struct dp_state {
static void
dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
{
struct nouveau_drm *drm = nouveau_drm(dev);
u8 sink[2];
NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw);
/* set desired link configuration on the source */
dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw,
......@@ -106,27 +111,29 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp)
if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)
sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
auxch_wr(dev, dp->auxch, DP_LINK_BW_SET, sink, 2);
nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2);
}
static void
dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern)
{
struct nouveau_drm *drm = nouveau_drm(dev);
u8 sink_tp;
NV_DEBUG_KMS(dev, "training pattern %d\n", pattern);
NV_DEBUG(drm, "training pattern %d\n", pattern);
dp->func->train_set(dev, dp->dcb, pattern);
auxch_rd(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
sink_tp &= ~DP_TRAINING_PATTERN_MASK;
sink_tp |= pattern;
auxch_wr(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1);
}
static int
dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
{
struct nouveau_drm *drm = nouveau_drm(dev);
int i;
for (i = 0; i < dp->link_nr; i++) {
......@@ -140,25 +147,26 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp)
if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5)
dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]);
NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]);
dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre);
}
return auxch_wr(dev, dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4);
return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4);
}
static int
dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
{
struct nouveau_drm *drm = nouveau_drm(dev);
int ret;
udelay(delay);
ret = auxch_rd(dev, dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6);
ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6);
if (ret)
return ret;
NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n",
NV_DEBUG(drm, "status %02x %02x %02x %02x %02x %02x\n",
dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3],
dp->stat[4], dp->stat[5]);
return 0;
......@@ -287,11 +295,14 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
struct nouveau_connector *nv_connector =
nouveau_encoder_connector_get(nv_encoder);
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
const u32 bw_list[] = { 270000, 162000, 0 };
const u32 *link_bw = bw_list;
struct dp_state dp;
dp.auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
if (!dp.auxch)
return false;
......@@ -307,7 +318,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.
*/
nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false);
gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false);
/* enable down-spreading, if possible */
dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1);
......@@ -350,7 +361,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
dp_link_train_fini(dev, &dp);
/* re-enable hotplug detect */
nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true);
gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true);
return true;
}
......@@ -359,10 +370,12 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
struct dp_train_func *func)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_drm *drm = nouveau_drm(encoder->dev);
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
struct nouveau_i2c_port *auxch;
u8 status;
auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index);
auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
if (!auxch)
return;
......@@ -371,7 +384,7 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate,
else
status = DP_SET_POWER_D3;
auxch_wr(encoder->dev, auxch, DP_SET_POWER, &status, 1);
nv_wraux(auxch, DP_SET_POWER, &status, 1);
if (mode == DRM_MODE_DPMS_ON)
nouveau_dp_link_train(encoder, datarate, func);
......@@ -381,17 +394,18 @@ static void
nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch,
u8 *dpcd)
{
struct nouveau_drm *drm = nouveau_drm(dev);
u8 buf[3];
if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
return;
if (!auxch_rd(dev, auxch, DP_SINK_OUI, buf, 3))
NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n",
if (!nv_rdaux(auxch, DP_SINK_OUI, buf, 3))
NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n",
buf[0], buf[1], buf[2]);
if (!auxch_rd(dev, auxch, DP_BRANCH_OUI, buf, 3))
NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n",
if (!nv_rdaux(auxch, DP_BRANCH_OUI, buf, 3))
NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n",
buf[0], buf[1], buf[2]);
}
......@@ -401,24 +415,26 @@ nouveau_dp_detect(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
struct nouveau_i2c_port *auxch;
u8 *dpcd = nv_encoder->dp.dpcd;
int ret;
auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index);
if (!auxch)
return false;
ret = auxch_rd(dev, auxch, DP_DPCD_REV, dpcd, 8);
ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8);
if (ret)
return false;
nv_encoder->dp.link_bw = 27000 * dpcd[1];
nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK;
NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n",
NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n",
nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]);
NV_DEBUG_KMS(dev, "encoder: %dx%d\n",
NV_DEBUG(drm, "encoder: %dx%d\n",
nv_encoder->dcb->dpconf.link_nr,
nv_encoder->dcb->dpconf.link_bw);
......@@ -427,7 +443,7 @@ nouveau_dp_detect(struct drm_encoder *encoder)
if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw)
nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw;
NV_DEBUG_KMS(dev, "maximum: %dx%d\n",
NV_DEBUG(drm, "maximum: %dx%d\n",
nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
nouveau_dp_probe_oui(dev, auxch, dpcd);
......
......@@ -22,6 +22,7 @@
* Authors: Ben Skeggs
*/
#include <linux/console.h>
#include <linux/module.h>
#include <linux/pci.h>
......@@ -34,24 +35,22 @@
#include <subdev/vm.h>
#include "nouveau_drm.h"
#include "nouveau_irq.h"
#include "nouveau_dma.h"
#include "nouveau_ttm.h"
#include "nouveau_gem.h"
#include "nouveau_agp.h"
#include "nouveau_vga.h"
#include "nouveau_pm.h"
#include "nouveau_acpi.h"
#include "nouveau_bios.h"
#include "nouveau_ioctl.h"
#include "nouveau_abi16.h"
#include "nouveau_fbcon.h"
#include "nouveau_fence.h"
#include "nouveau_ttm.h"
int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *);
void nouveau_pci_remove(struct pci_dev *);
int nouveau_pci_suspend(struct pci_dev *, pm_message_t);
int nouveau_pci_resume(struct pci_dev *);
int __init nouveau_init(struct pci_driver *);
void __exit nouveau_exit(struct pci_driver *);
int nouveau_load(struct drm_device *, unsigned long);
int nouveau_unload(struct drm_device *);
MODULE_PARM_DESC(config, "option string to pass to driver core");
static char *nouveau_config;
module_param_named(config, nouveau_config, charp, 0400);
......@@ -64,6 +63,12 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
static int nouveau_noaccel = 0;
module_param_named(noaccel, nouveau_noaccel, int, 0400);
MODULE_PARM_DESC(modeset, "enable driver");
int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400);
static struct drm_driver driver;
static u64
nouveau_name(struct pci_dev *pdev)
{
......@@ -206,7 +211,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent)
pci_set_master(pdev);
ret = nouveau_pci_probe(pdev, pent);
ret = drm_get_pci_dev(pdev, pent, &driver);
if (ret) {
nouveau_object_ref(NULL, (struct nouveau_object **)&device);
return ret;
......@@ -224,13 +229,14 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
int ret;
ret = nouveau_cli_create(pdev, 0, sizeof(*drm), (void**)&drm);
dev->dev_private = drm;
if (ret)
return ret;
dev->dev_private = drm;
drm->dev = dev;
INIT_LIST_HEAD(&drm->clients);
spin_lock_init(&drm->tile.lock);
drm->dev = dev;
/* make sure AGP controller is in a consistent state before we
* (possibly) execute vbios init tables (see nouveau_agp.h)
......@@ -266,9 +272,15 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
if (ret)
goto fail_device;
/* workaround an odd issue on nvc1 by disabling the device's
* nosnoop capability. hopefully won't cause issues until a
* better fix is found - assuming there is one...
*/
device = nv_device(drm->device);
if (nv_device(drm->device)->chipset == 0xc1)
nv_mask(device, 0x00088080, 0x00000800, 0x00000000);
/* initialise AGP */
nouveau_vga_init(drm);
nouveau_agp_init(drm);
if (device->card_type >= NV_50) {
......@@ -280,18 +292,43 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
ret = nouveau_ttm_init(drm);
if (ret)
goto fail_device;
goto fail_ttm;
ret = nouveau_bios_init(dev);
if (ret)
goto fail_bios;
ret = nouveau_irq_init(dev);
if (ret)
goto fail_irq;
ret = nouveau_load(dev, flags);
ret = nouveau_display_create(dev);
if (ret)
goto fail_load;
goto fail_dispctor;
if (dev->mode_config.num_crtc) {
ret = nouveau_display_init(dev);
if (ret)
goto fail_dispinit;
}
nouveau_pm_init(dev);
nouveau_accel_init(drm);
nouveau_fbcon_init(dev);
return 0;
fail_load:
fail_dispinit:
nouveau_display_destroy(dev);
fail_dispctor:
nouveau_irq_fini(dev);
fail_irq:
nouveau_bios_takedown(dev);
fail_bios:
nouveau_ttm_fini(drm);
fail_ttm:
nouveau_agp_fini(drm);
nouveau_vga_fini(drm);
fail_device:
nouveau_cli_destroy(&drm->client);
return ret;
......@@ -300,21 +337,23 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
int
nouveau_drm_unload(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct pci_dev *pdev = dev->pdev;
int ret;
struct nouveau_drm *drm = nouveau_drm(dev);
nouveau_fbcon_fini(dev);
nouveau_accel_fini(drm);
ret = nouveau_unload(dev);
if (ret)
return ret;
nouveau_pm_fini(dev);
nouveau_display_fini(dev);
nouveau_display_destroy(dev);
nouveau_irq_fini(dev);
nouveau_bios_takedown(dev);
nouveau_ttm_fini(drm);
nouveau_agp_fini(drm);
nouveau_vga_fini(drm);
pci_set_drvdata(pdev, drm->client.base.device);
nouveau_cli_destroy(&drm->client);
return 0;
}
......@@ -322,9 +361,13 @@ nouveau_drm_unload(struct drm_device *dev)
static void
nouveau_drm_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_object *device;
nouveau_pci_remove(pdev);
device = pci_get_drvdata(pdev);
device = drm->client.base.device;
drm_put_dev(dev);
nouveau_object_ref(NULL, &device);
nouveau_object_debug();
}
......@@ -333,7 +376,7 @@ int
nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_cli *cli;
int ret;
......@@ -344,8 +387,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
NV_INFO(drm, "suspending fbcon...\n");
nouveau_fbcon_set_suspend(dev, 1);
NV_INFO(drm, "suspending drm...\n");
ret = nouveau_pci_suspend(pdev, pm_state);
NV_INFO(drm, "suspending display...\n");
ret = nouveau_display_suspend(dev);
if (ret)
return ret;
......@@ -383,7 +426,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
nouveau_client_init(&cli->base);
}
nouveau_pci_resume(pdev);
NV_INFO(drm, "resuming display...\n");
nouveau_display_resume(dev);
return ret;
}
......@@ -391,7 +435,7 @@ int
nouveau_drm_resume(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_cli *cli;
int ret;
......@@ -419,7 +463,13 @@ nouveau_drm_resume(struct pci_dev *pdev)
if (drm->fence && nouveau_fence(drm)->resume)
nouveau_fence(drm)->resume(drm);
return nouveau_pci_resume(pdev);
nouveau_run_vbios_init(dev);
nouveau_irq_postinstall(dev);
nouveau_pm_resume(dev);
NV_INFO(drm, "resuming display...\n");
nouveau_display_resume(dev);
return 0;
}
int
......@@ -472,6 +522,90 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv)
nouveau_cli_destroy(cli);
}
static struct drm_ioctl_desc
nouveau_ioctls[] = {
DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH),
};
static const struct file_operations
nouveau_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
.mmap = nouveau_ttm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
.read = drm_read,
#if defined(CONFIG_COMPAT)
.compat_ioctl = nouveau_compat_ioctl,
#endif
.llseek = noop_llseek,
};
static struct drm_driver
driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
DRIVER_MODESET | DRIVER_PRIME,
.load = nouveau_drm_load,
.unload = nouveau_drm_unload,
.open = nouveau_drm_open,
.preclose = nouveau_drm_preclose,
.postclose = nouveau_drm_postclose,
.lastclose = nouveau_vga_lastclose,
.irq_preinstall = nouveau_irq_preinstall,
.irq_postinstall = nouveau_irq_postinstall,
.irq_uninstall = nouveau_irq_uninstall,
.irq_handler = nouveau_irq_handler,
.get_vblank_counter = drm_vblank_count,
.enable_vblank = nouveau_vblank_enable,
.disable_vblank = nouveau_vblank_disable,
.ioctls = nouveau_ioctls,
.fops = &nouveau_driver_fops,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = nouveau_gem_prime_export,
.gem_prime_import = nouveau_gem_prime_import,
.gem_init_object = nouveau_gem_object_new,
.gem_free_object = nouveau_gem_object_del,
.gem_open_object = nouveau_gem_object_open,
.gem_close_object = nouveau_gem_object_close,
.dumb_create = nouveau_display_dumb_create,
.dumb_map_offset = nouveau_display_dumb_map_offset,
.dumb_destroy = nouveau_display_dumb_destroy,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
#ifdef GIT_REVISION
.date = GIT_REVISION,
#else
.date = DRIVER_DATE,
#endif
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
};
static struct pci_device_id
nouveau_drm_pci_table[] = {
{
......@@ -500,19 +634,38 @@ nouveau_drm_pci_driver = {
static int __init
nouveau_drm_init(void)
{
return nouveau_init(&nouveau_drm_pci_driver);
driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls);
if (nouveau_modeset == -1) {
#ifdef CONFIG_VGA_CONSOLE
if (vgacon_text_force())
nouveau_modeset = 0;
else
#endif
nouveau_modeset = 1;
}
if (!nouveau_modeset)
return 0;
nouveau_register_dsm_handler();
return drm_pci_init(&driver, &nouveau_drm_pci_driver);
}
static void __exit
nouveau_drm_exit(void)
{
nouveau_exit(&nouveau_drm_pci_driver);
if (!nouveau_modeset)
return;
drm_pci_exit(&driver, &nouveau_drm_pci_driver);
nouveau_unregister_dsm_handler();
}
module_init(nouveau_drm_init);
module_exit(nouveau_drm_exit);
MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table);
MODULE_AUTHOR("Nouveau Project");
MODULE_DESCRIPTION("nVidia Riva/TNT/GeForce/Quadro/Tesla");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights");
#ifndef __NOUVEAU_DRMCLI_H__
#define __NOUVEAU_DRMCLI_H__
#define DRIVER_AUTHOR "Nouveau Project"
#define DRIVER_EMAIL "nouveau@lists.freedesktop.org"
#define DRIVER_NAME "nouveau"
#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla"
#define DRIVER_DATE "20120801"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 1
#define DRIVER_PATCHLEVEL 0
#include <core/client.h>
#include <subdev/vm.h>
......@@ -19,8 +30,8 @@ struct nouveau_channel;
#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
#include "nouveau_revcompat.h"
#include "nouveau_fence.h"
#include "nouveau_bios.h"
struct nouveau_drm_tile {
struct nouveau_fence *fence;
......@@ -96,13 +107,25 @@ struct nouveau_drm {
spinlock_t lock;
} tile;
/* modesetting */
struct nvbios vbios;
struct nouveau_display *display;
struct backlight_device *backlight;
/* power management */
struct nouveau_pm *pm;
};
static inline struct nouveau_drm *
nouveau_drm(struct drm_device *dev)
{
return nouveau_newpriv(dev);
return dev->dev_private;
}
static inline struct nouveau_device *
nouveau_dev(struct drm_device *dev)
{
return nv_device(nouveau_drm(dev)->device);
}
int nouveau_drm_suspend(struct pci_dev *, pm_message_t);
......
/*
* Copyright 2005 Stephane Marchesin.
* All Rights Reserved.
*
* 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 (including the next
* paragraph) 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
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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.
*/
#include <linux/console.h>
#include <linux/module.h>
#include "drmP.h"
#include "drm.h"
#include "drm_crtc_helper.h"
#include "nouveau_drv.h"
#include "nouveau_abi16.h"
#include "nouveau_hw.h"
#include "nouveau_fb.h"
#include "nouveau_fbcon.h"
#include "nouveau_fence.h"
#include "nouveau_pm.h"
#include "nv50_display.h"
#include "nouveau_acpi.h"
#include "nouveau_ioctl.h"
#include "drm_pciids.h"
MODULE_PARM_DESC(modeset, "Enable kernel modesetting");
int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400);
MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
int nouveau_vram_notify = 0;
module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
MODULE_PARM_DESC(vram_type, "Override detected VRAM type");
char *nouveau_vram_type;
module_param_named(vram_type, nouveau_vram_type, charp, 0400);
MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
int nouveau_duallink = 1;
module_param_named(duallink, nouveau_duallink, int, 0400);
MODULE_PARM_DESC(uscript_lvds, "LVDS output script table ID (>=GeForce 8)");
int nouveau_uscript_lvds = -1;
module_param_named(uscript_lvds, nouveau_uscript_lvds, int, 0400);
MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)");
int nouveau_uscript_tmds = -1;
module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400);
MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
int nouveau_ignorelid = 0;
module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
MODULE_PARM_DESC(force_post, "Force POST");
int nouveau_force_post = 0;
module_param_named(force_post, nouveau_force_post, int, 0400);
MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type");
int nouveau_override_conntype = 0;
module_param_named(override_conntype, nouveau_override_conntype, int, 0400);
MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
int nouveau_tv_disable = 0;
module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
"\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
"\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
"\t\tDefault: PAL\n"
"\t\t*NOTE* Ignored for cards with external TV encoders.");
char *nouveau_tv_norm;
module_param_named(tv_norm, nouveau_tv_norm, charp, 0400);
MODULE_PARM_DESC(perflvl, "Performance level (default: boot)");
char *nouveau_perflvl;
module_param_named(perflvl, nouveau_perflvl, charp, 0400);
MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)");
int nouveau_perflvl_wr;
module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
MODULE_PARM_DESC(msi, "Enable MSI (default: off)");
int nouveau_msi;
module_param_named(msi, nouveau_msi, int, 0400);
MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)");
int nouveau_ctxfw;
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS");
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);
#endif
static struct drm_driver driver;
int __devinit
nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
return drm_get_pci_dev(pdev, ent, &driver);
}
void
nouveau_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
drm_put_dev(dev);
}
int
nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct drm_crtc *crtc;
NV_INFO(dev, "Disabling display...\n");
nouveau_display_fini(dev);
NV_INFO(dev, "Unpinning framebuffer(s)...\n");
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_framebuffer *nouveau_fb;
nouveau_fb = nouveau_framebuffer(crtc->fb);
if (!nouveau_fb || !nouveau_fb->nvbo)
continue;
nouveau_bo_unpin(nouveau_fb->nvbo);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
}
return 0;
}
int
nouveau_pci_resume(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct drm_crtc *crtc;
int ret;
ret = nouveau_run_vbios_init(dev);
if (ret)
return ret;
nouveau_irq_postinstall(dev);
#if 0
/* Re-write SKIPS, they'll have been lost over the suspend */
if (nouveau_vram_pushbuf) {
struct nouveau_channel *chan;
int j;
for (i = 0; i < (pfifo ? pfifo->channels : 0); i++) {
chan = dev_priv->channels.ptr[i];
if (!chan || !chan->pushbuf_bo)
continue;
for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
nouveau_bo_wr32(chan->pushbuf_bo, i, 0);
}
}
#endif
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;
nouveau_fb = nouveau_framebuffer(crtc->fb);
if (!nouveau_fb || !nouveau_fb->nvbo)
continue;
nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
if (!ret)
ret = nouveau_bo_map(nv_crtc->cursor.nvbo);
if (ret)
NV_ERROR(dev, "Could not pin/map cursor.\n");
}
nouveau_fbcon_set_suspend(dev, 0);
nouveau_fbcon_zfill_all(dev);
nouveau_display_init(dev);
/* Force CLUT to get re-loaded during modeset */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
nv_crtc->lut.depth = 0;
}
drm_helper_resume_force_mode(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;
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);
}
return 0;
}
static struct drm_ioctl_desc nouveau_ioctls[] = {
DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH),
};
static const struct file_operations nouveau_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
.mmap = nouveau_ttm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
.read = drm_read,
#if defined(CONFIG_COMPAT)
.compat_ioctl = nouveau_compat_ioctl,
#endif
.llseek = noop_llseek,
};
int nouveau_drm_load(struct drm_device *, unsigned long);
int nouveau_drm_unload(struct drm_device *);
int nouveau_drm_open(struct drm_device *, struct drm_file *);
void nouveau_drm_preclose(struct drm_device *dev, struct drm_file *);
void nouveau_drm_postclose(struct drm_device *, struct drm_file *);
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
DRIVER_MODESET | DRIVER_PRIME,
.load = nouveau_drm_load,
.firstopen = nouveau_firstopen,
.lastclose = nouveau_lastclose,
.unload = nouveau_drm_unload,
.open = nouveau_drm_open,
.preclose = nouveau_drm_preclose,
.postclose = nouveau_drm_postclose,
.irq_preinstall = nouveau_irq_preinstall,
.irq_postinstall = nouveau_irq_postinstall,
.irq_uninstall = nouveau_irq_uninstall,
.irq_handler = nouveau_irq_handler,
.get_vblank_counter = drm_vblank_count,
.enable_vblank = nouveau_vblank_enable,
.disable_vblank = nouveau_vblank_disable,
.ioctls = nouveau_ioctls,
.fops = &nouveau_driver_fops,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = nouveau_gem_prime_export,
.gem_prime_import = nouveau_gem_prime_import,
.gem_init_object = nouveau_gem_object_new,
.gem_free_object = nouveau_gem_object_del,
.gem_open_object = nouveau_gem_object_open,
.gem_close_object = nouveau_gem_object_close,
.dumb_create = nouveau_display_dumb_create,
.dumb_map_offset = nouveau_display_dumb_map_offset,
.dumb_destroy = nouveau_display_dumb_destroy,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
#ifdef GIT_REVISION
.date = GIT_REVISION,
#else
.date = DRIVER_DATE,
#endif
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
};
int __init nouveau_init(struct pci_driver *pdrv)
{
driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls);
if (nouveau_modeset == -1) {
#ifdef CONFIG_VGA_CONSOLE
if (vgacon_text_force())
nouveau_modeset = 0;
else
#endif
nouveau_modeset = 1;
}
if (!nouveau_modeset)
return 0;
nouveau_register_dsm_handler();
return drm_pci_init(&driver, pdrv);
}
void __exit nouveau_exit(struct pci_driver *pdrv)
{
if (!nouveau_modeset)
return;
drm_pci_exit(&driver, pdrv);
nouveau_unregister_dsm_handler();
}
/*
* Copyright 2005 Stephane Marchesin.
* All Rights Reserved.
*
* 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 (including the next
* paragraph) 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
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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_DRV_H__
#define __NOUVEAU_DRV_H__
#define DRIVER_AUTHOR "Stephane Marchesin"
#define DRIVER_EMAIL "nouveau@lists.freedesktop.org"
#define DRIVER_NAME "nouveau"
#define DRIVER_DESC "nVidia Riva/TNT/GeForce"
#define DRIVER_DATE "20120316"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
#define NOUVEAU_FAMILY 0x0000FFFF
#define NOUVEAU_FLAGS 0xFFFF0000
#include "ttm/ttm_bo_api.h"
#include "ttm/ttm_bo_driver.h"
#include "ttm/ttm_placement.h"
#include "ttm/ttm_memory.h"
#include "ttm/ttm_module.h"
#define XXX_THIS_IS_A_HACK
#include <subdev/vm.h>
#include <subdev/fb.h>
#include <core/gpuobj.h>
enum blah {
NV_MEM_TYPE_UNKNOWN = 0,
NV_MEM_TYPE_STOLEN,
NV_MEM_TYPE_SGRAM,
NV_MEM_TYPE_SDRAM,
NV_MEM_TYPE_DDR1,
NV_MEM_TYPE_DDR2,
NV_MEM_TYPE_DDR3,
NV_MEM_TYPE_GDDR2,
NV_MEM_TYPE_GDDR3,
NV_MEM_TYPE_GDDR4,
NV_MEM_TYPE_GDDR5
};
#include <nouveau_drm.h>
#include "nouveau_reg.h"
#include <nouveau_bios.h>
#include <subdev/bios/pll.h>
#include "nouveau_compat.h"
#define nouveau_gpuobj_new(d,c,s,a,f,o) \
_nouveau_gpuobj_new((d), NULL, (s), (a), (f), (o))
#define nouveau_vm_new(d,o,l,m,v) \
_nouveau_vm_new((d), (o), (l), (m), (v))
#define nv50_vm_flush_engine(d,e) \
_nv50_vm_flush_engine((d), (e))
#include "nouveau_bo.h"
#include "nouveau_gem.h"
struct nouveau_page_flip_state {
struct list_head head;
struct drm_pending_vblank_event *event;
int crtc, bpp, pitch, x, y;
uint64_t offset;
};
struct nouveau_display_engine {
void *priv;
int (*early_init)(struct drm_device *);
void (*late_takedown)(struct drm_device *);
int (*create)(struct drm_device *);
void (*destroy)(struct drm_device *);
int (*init)(struct drm_device *);
void (*fini)(struct drm_device *);
struct drm_property *dithering_mode;
struct drm_property *dithering_depth;
struct drm_property *underscan_property;
struct drm_property *underscan_hborder_property;
struct drm_property *underscan_vborder_property;
/* not really hue and saturation: */
struct drm_property *vibrant_hue_property;
struct drm_property *color_vibrance_property;
};
struct nouveau_pm_voltage_level {
u32 voltage; /* microvolts */
u8 vid;
};
struct nouveau_pm_voltage {
bool supported;
u8 version;
u8 vid_mask;
struct nouveau_pm_voltage_level *level;
int nr_level;
};
/* Exclusive upper limits */
#define NV_MEM_CL_DDR2_MAX 8
#define NV_MEM_WR_DDR2_MAX 9
#define NV_MEM_CL_DDR3_MAX 17
#define NV_MEM_WR_DDR3_MAX 17
#define NV_MEM_CL_GDDR3_MAX 16
#define NV_MEM_WR_GDDR3_MAX 18
#define NV_MEM_CL_GDDR5_MAX 21
#define NV_MEM_WR_GDDR5_MAX 20
struct nouveau_pm_memtiming {
int id;
u32 reg[9];
u32 mr[4];
u8 tCWL;
u8 odt;
u8 drive_strength;
};
struct nouveau_pm_tbl_header {
u8 version;
u8 header_len;
u8 entry_cnt;
u8 entry_len;
};
struct nouveau_pm_tbl_entry {
u8 tWR;
u8 tWTR;
u8 tCL;
u8 tRC;
u8 empty_4;
u8 tRFC; /* Byte 5 */
u8 empty_6;
u8 tRAS; /* Byte 7 */
u8 empty_8;
u8 tRP; /* Byte 9 */
u8 tRCDRD;
u8 tRCDWR;
u8 tRRD;
u8 tUNK_13;
u8 RAM_FT1; /* 14, a bitmask of random RAM features */
u8 empty_15;
u8 tUNK_16;
u8 empty_17;
u8 tUNK_18;
u8 tCWL;
u8 tUNK_20, tUNK_21;
};
struct nouveau_pm_profile;
struct nouveau_pm_profile_func {
void (*destroy)(struct nouveau_pm_profile *);
void (*init)(struct nouveau_pm_profile *);
void (*fini)(struct nouveau_pm_profile *);
struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *);
};
struct nouveau_pm_profile {
const struct nouveau_pm_profile_func *func;
struct list_head head;
char name[8];
};
#define NOUVEAU_PM_MAX_LEVEL 8
struct nouveau_pm_level {
struct nouveau_pm_profile profile;
struct device_attribute dev_attr;
char name[32];
int id;
struct nouveau_pm_memtiming timing;
u32 memory;
u16 memscript;
u32 core;
u32 shader;
u32 rop;
u32 copy;
u32 daemon;
u32 vdec;
u32 dom6;
u32 unka0; /* nva3:nvc0 */
u32 hub01; /* nvc0- */
u32 hub06; /* nvc0- */
u32 hub07; /* nvc0- */
u32 volt_min; /* microvolts */
u32 volt_max;
u8 fanspeed;
};
struct nouveau_pm_temp_sensor_constants {
u16 offset_constant;
s16 offset_mult;
s16 offset_div;
s16 slope_mult;
s16 slope_div;
};
struct nouveau_pm_threshold_temp {
s16 critical;
s16 down_clock;
s16 fan_boost;
};
struct nouveau_pm_fan {
u32 percent;
u32 min_duty;
u32 max_duty;
u32 pwm_freq;
u32 pwm_divisor;
};
struct nouveau_pm_engine {
struct nouveau_pm_voltage voltage;
struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL];
int nr_perflvl;
struct nouveau_pm_temp_sensor_constants sensor_constants;
struct nouveau_pm_threshold_temp threshold_temp;
struct nouveau_pm_fan fan;
struct nouveau_pm_profile *profile_ac;
struct nouveau_pm_profile *profile_dc;
struct nouveau_pm_profile *profile;
struct list_head profiles;
struct nouveau_pm_level boot;
struct nouveau_pm_level *cur;
struct device *hwmon;
struct notifier_block acpi_nb;
int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *);
void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *);
int (*clocks_set)(struct drm_device *, void *);
int (*voltage_get)(struct drm_device *);
int (*voltage_set)(struct drm_device *, int voltage);
int (*pwm_get)(struct drm_device *, int line, u32*, u32*);
int (*pwm_set)(struct drm_device *, int line, u32, u32);
int (*temp_get)(struct drm_device *);
};
struct nouveau_engine {
struct nouveau_display_engine display;
struct nouveau_pm_engine pm;
};
enum nouveau_card_type {
NV_04 = 0x04,
NV_10 = 0x10,
NV_20 = 0x20,
NV_30 = 0x30,
NV_40 = 0x40,
NV_50 = 0x50,
NV_C0 = 0xc0,
NV_D0 = 0xd0,
NV_E0 = 0xe0,
};
struct drm_nouveau_private {
struct drm_device *dev;
void *newpriv;
/* the card type, takes NV_* as values */
enum nouveau_card_type card_type;
/* exact chipset, derived from NV_PMC_BOOT_0 */
int chipset;
u32 crystal;
/* interrupt handling */
void (*irq_handler[32])(struct drm_device *);
bool msi_enabled;
struct nouveau_engine engine;
/* For PFIFO and PGRAPH. */
spinlock_t context_switch_lock;
struct nvbios vbios;
};
static inline struct drm_nouveau_private *
nouveau_private(struct drm_device *dev)
{
return dev->dev_private;
}
/* nouveau_drv.c */
extern int nouveau_modeset;
extern int nouveau_duallink;
extern int nouveau_uscript_lvds;
extern int nouveau_uscript_tmds;
extern int nouveau_vram_pushbuf;
extern int nouveau_vram_notify;
extern char *nouveau_vram_type;
extern int nouveau_fbpercrtc;
extern int nouveau_tv_disable;
extern char *nouveau_tv_norm;
extern int nouveau_ignorelid;
extern int nouveau_force_post;
extern int nouveau_override_conntype;
extern char *nouveau_perflvl;
extern int nouveau_perflvl_wr;
extern int nouveau_msi;
extern int nouveau_ctxfw;
extern int nouveau_mxmdcb;
extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state);
extern int nouveau_pci_resume(struct pci_dev *pdev);
/* nouveau_state.c */
extern int nouveau_load(struct drm_device *, unsigned long flags);
extern int nouveau_firstopen(struct drm_device *);
extern void nouveau_lastclose(struct drm_device *);
extern int nouveau_unload(struct drm_device *);
extern int nouveau_card_init(struct drm_device *);
/* nouveau_mem.c */
extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq,
struct nouveau_pm_memtiming *);
extern void nouveau_mem_timing_read(struct drm_device *,
struct nouveau_pm_memtiming *);
/* nouveau_irq.c */
extern int nouveau_irq_init(struct drm_device *);
extern void nouveau_irq_fini(struct drm_device *);
extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
extern void nouveau_irq_register(struct drm_device *, int status_bit,
void (*)(struct drm_device *));
extern void nouveau_irq_unregister(struct drm_device *, int status_bit);
extern void nouveau_irq_preinstall(struct drm_device *);
extern int nouveau_irq_postinstall(struct drm_device *);
extern void nouveau_irq_uninstall(struct drm_device *);
/* nouveau_backlight.c */
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
extern int nouveau_backlight_init(struct drm_device *);
extern void nouveau_backlight_exit(struct drm_device *);
#else
static inline int nouveau_backlight_init(struct drm_device *dev)
{
return 0;
}
static inline void nouveau_backlight_exit(struct drm_device *dev) { }
#endif
/* nouveau_bios.c */
extern int nouveau_bios_init(struct drm_device *);
extern void nouveau_bios_takedown(struct drm_device *dev);
extern int nouveau_run_vbios_init(struct drm_device *);
extern struct dcb_connector_table_entry *
nouveau_bios_connector_entry(struct drm_device *, int index);
extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk,
struct dcb_output *, int crtc);
extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *);
extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *);
extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk,
bool *dl, bool *if_is_24bit);
extern int run_tmds_table(struct drm_device *, struct dcb_output *,
int head, int pxclk);
extern int call_lvds_script(struct drm_device *, struct dcb_output *, int head,
enum LVDS_script, int pxclk);
bool bios_encoder_match(struct dcb_output *, u32 hash);
/* nouveau_ttm.c */
int nouveau_ttm_global_init(struct drm_nouveau_private *);
void nouveau_ttm_global_release(struct drm_nouveau_private *);
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 *);
/* nvd0_display.c */
extern int nvd0_display_create(struct drm_device *);
extern void nvd0_display_destroy(struct drm_device *);
extern int nvd0_display_init(struct drm_device *);
extern void nvd0_display_fini(struct drm_device *);
struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int crtc);
void nvd0_display_flip_stop(struct drm_crtc *);
int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
struct nouveau_channel *, u32 swap_interval);
/* nouveau_display.c */
int nouveau_display_create(struct drm_device *dev);
void nouveau_display_destroy(struct drm_device *dev);
int nouveau_display_init(struct drm_device *dev);
void nouveau_display_fini(struct drm_device *dev);
int nouveau_vblank_enable(struct drm_device *dev, int crtc);
void nouveau_vblank_disable(struct drm_device *dev, int crtc);
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event);
int nouveau_finish_page_flip(struct nouveau_channel *,
struct nouveau_page_flip_state *);
int nouveau_display_dumb_create(struct drm_file *, struct drm_device *,
struct drm_mode_create_dumb *args);
int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
uint32_t handle, uint64_t *offset);
int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *,
uint32_t handle);
#ifndef ioread32_native
#ifdef __BIG_ENDIAN
#define ioread16_native ioread16be
#define iowrite16_native iowrite16be
#define ioread32_native ioread32be
#define iowrite32_native iowrite32be
#else /* def __BIG_ENDIAN */
#define ioread16_native ioread16
#define iowrite16_native iowrite16
#define ioread32_native ioread32
#define iowrite32_native iowrite32
#endif /* def __BIG_ENDIAN else */
#endif /* !ioread32_native */
/* register access */
#define nv_rd08 _nv_rd08
#define nv_wr08 _nv_wr08
#define nv_rd32 _nv_rd32
#define nv_wr32 _nv_wr32
#define nv_mask _nv_mask
#define nv_wait(dev, reg, mask, val) \
nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val))
#define nv_wait_ne(dev, reg, mask, val) \
nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val))
#define nv_wait_cb(dev, func, data) \
nouveau_wait_cb(dev, 2000000000ULL, (func), (data))
/*
* Logging
* Argument d is (struct drm_device *).
*/
#define NV_PRINTK(level, d, fmt, arg...) \
printk(level "[" DRM_NAME "] " DRIVER_NAME " %s: " fmt, \
pci_name(d->pdev), ##arg)
#ifndef NV_DEBUG_NOTRACE
#define NV_DEBUG(d, fmt, arg...) do { \
if (drm_debug & DRM_UT_DRIVER) { \
NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \
__LINE__, ##arg); \
} \
} while (0)
#define NV_DEBUG_KMS(d, fmt, arg...) do { \
if (drm_debug & DRM_UT_KMS) { \
NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \
__LINE__, ##arg); \
} \
} while (0)
#else
#define NV_DEBUG(d, fmt, arg...) do { \
if (drm_debug & DRM_UT_DRIVER) \
NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \
} while (0)
#define NV_DEBUG_KMS(d, fmt, arg...) do { \
if (drm_debug & DRM_UT_KMS) \
NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \
} while (0)
#endif
#define NV_ERROR(d, fmt, arg...) NV_PRINTK(KERN_ERR, d, fmt, ##arg)
#define NV_INFO(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg)
#define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg)
#define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg)
#define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg)
#define NV_WARNONCE(d, fmt, arg...) do { \
static int _warned = 0; \
if (!_warned) { \
NV_WARN(d, fmt, ##arg); \
_warned = 1; \
} \
} while(0)
static inline bool
nv_two_heads(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
const int impl = dev->pci_device & 0x0ff0;
if (dev_priv->card_type >= NV_10 && impl != 0x0100 &&
impl != 0x0150 && impl != 0x01a0 && impl != 0x0200)
return true;
return false;
}
static inline bool
nv_gf4_disp_arch(struct drm_device *dev)
{
return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110;
}
static inline bool
nv_two_reg_pll(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
const int impl = dev->pci_device & 0x0ff0;
if (impl == 0x0310 || impl == 0x0340 || dev_priv->card_type >= NV_40)
return true;
return false;
}
static inline bool
nv_match_device(struct drm_device *dev, unsigned device,
unsigned sub_vendor, unsigned sub_device)
{
return dev->pdev->device == device &&
dev->pdev->subsystem_vendor == sub_vendor &&
dev->pdev->subsystem_device == sub_device;
}
static inline struct nv04_display *
nv04_display(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
return dev_priv->engine.display.priv;
}
#endif /* __NOUVEAU_DRV_H__ */
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* 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 (including the
* next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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_FRB_H__
#define __NOUVEAU_FRB_H__
struct nouveau_framebuffer {
struct drm_framebuffer base;
struct nouveau_bo *nvbo;
struct nouveau_vma vma;
u32 r_dma;
u32 r_format;
u32 r_pitch;
};
static inline struct nouveau_framebuffer *
nouveau_framebuffer(struct drm_framebuffer *fb)
{
return container_of(fb, struct nouveau_framebuffer, base);
}
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__ */
......@@ -47,7 +47,6 @@
#include "nouveau_drm.h"
#include "nouveau_gem.h"
#include "nouveau_bo.h"
#include "nouveau_fb.h"
#include "nouveau_fbcon.h"
#include "nouveau_chan.h"
......@@ -66,7 +65,7 @@ static void
nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev);
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
struct nouveau_device *device = nv_device(drm->device);
int ret;
......@@ -98,7 +97,7 @@ static void
nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev);
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
struct nouveau_device *device = nv_device(drm->device);
int ret;
......@@ -130,7 +129,7 @@ static void
nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev);
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
struct nouveau_device *device = nv_device(drm->device);
int ret;
......@@ -162,7 +161,7 @@ static int
nouveau_fbcon_sync(struct fb_info *info)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev);
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
struct nouveau_channel *chan = drm->channel;
int ret;
......@@ -257,7 +256,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *fbcon,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = fbcon->dev;
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_device *device = nv_device(drm->device);
struct fb_info *info;
struct drm_framebuffer *fb;
......@@ -410,7 +409,7 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper,
void
nouveau_fbcon_output_poll_changed(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
drm_fb_helper_hotplug_event(&drm->fbcon->helper);
}
......@@ -442,7 +441,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
void nouveau_fbcon_gpu_lockup(struct fb_info *info)
{
struct nouveau_fbdev *fbcon = info->par;
struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev);
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
NV_ERROR(drm, "GPU lockup - switching to software fbcon\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
......@@ -458,7 +457,7 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
int
nouveau_fbcon_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_fb *pfb = nouveau_fb(drm->device);
struct nouveau_fbdev *fbcon;
int preferred_bpp;
......@@ -499,7 +498,7 @@ nouveau_fbcon_init(struct drm_device *dev)
void
nouveau_fbcon_fini(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
if (!drm->fbcon)
return;
......@@ -511,7 +510,7 @@ nouveau_fbcon_fini(struct drm_device *dev)
void nouveau_fbcon_save_disable_accel(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
......@@ -519,13 +518,13 @@ void nouveau_fbcon_save_disable_accel(struct drm_device *dev)
void nouveau_fbcon_restore_accel(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
}
void nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
console_lock();
if (state == 0)
nouveau_fbcon_save_disable_accel(dev);
......@@ -537,6 +536,6 @@ void nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
void nouveau_fbcon_zfill_all(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
nouveau_fbcon_zfill(dev, drm->fbcon);
}
......@@ -29,7 +29,7 @@
#include "drm_fb_helper.h"
#include "nouveau_fb.h"
#include "nouveau_display.h"
struct nouveau_fbdev {
struct drm_fb_helper helper;
......
......@@ -550,7 +550,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
struct drm_nouveau_gem_pushbuf *req,
struct drm_nouveau_gem_pushbuf_bo *bo)
{
struct nouveau_drm *drm = nouveau_newpriv(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
int ret = 0;
unsigned i;
......
......@@ -23,7 +23,7 @@
*/
#include "drmP.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
......@@ -31,10 +31,10 @@
static bool
hdmi_sor(struct drm_encoder *encoder)
{
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
if (dev_priv->chipset < 0xa3 ||
dev_priv->chipset == 0xaa ||
dev_priv->chipset == 0xac)
struct nouveau_drm *drm = nouveau_drm(encoder->dev);
if (nv_device(drm->device)->chipset < 0xa3 ||
nv_device(drm->device)->chipset == 0xaa ||
nv_device(drm->device)->chipset == 0xac)
return false;
return true;
}
......@@ -52,13 +52,15 @@ hdmi_base(struct drm_encoder *encoder)
static void
hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val)
{
nv_wr32(encoder->dev, hdmi_base(encoder) + reg, val);
struct nouveau_device *device = nouveau_dev(encoder->dev);
nv_wr32(device, hdmi_base(encoder) + reg, val);
}
static u32
hdmi_rd32(struct drm_encoder *encoder, u32 reg)
{
return nv_rd32(encoder->dev, hdmi_base(encoder) + reg);
struct nouveau_device *device = nouveau_dev(encoder->dev);
return nv_rd32(device, hdmi_base(encoder) + reg);
}
static u32
......@@ -73,12 +75,11 @@ static void
nouveau_audio_disconnect(struct drm_encoder *encoder)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct nouveau_device *device = nouveau_dev(encoder->dev);
u32 or = nv_encoder->or * 0x800;
if (hdmi_sor(encoder)) {
nv_mask(dev, 0x61c448 + or, 0x00000003, 0x00000000);
}
if (hdmi_sor(encoder))
nv_mask(device, 0x61c448 + or, 0x00000003, 0x00000000);
}
static void
......@@ -86,8 +87,8 @@ nouveau_audio_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_device *device = nouveau_dev(encoder->dev);
struct nouveau_connector *nv_connector;
struct drm_device *dev = encoder->dev;
u32 or = nv_encoder->or * 0x800;
int i;
......@@ -98,16 +99,16 @@ nouveau_audio_mode_set(struct drm_encoder *encoder,
}
if (hdmi_sor(encoder)) {
nv_mask(dev, 0x61c448 + or, 0x00000001, 0x00000001);
nv_mask(device, 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]);
nv_wr32(device, 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);
nv_wr32(device, 0x61c440 + or, (i << 8) | 0x00);
nv_mask(device, 0x61c448 + or, 0x00000002, 0x00000002);
}
}
}
......@@ -219,9 +220,9 @@ void
nouveau_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct nouveau_device *device = nouveau_dev(encoder->dev);
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);
......@@ -238,9 +239,9 @@ nouveau_hdmi_mode_set(struct drm_encoder *encoder,
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 */
nv_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
nv_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
nv_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
/* value matches nvidia binary driver, and tegra constant */
rekey = 56;
......
......@@ -24,7 +24,6 @@
#define __NOUVEAU_HW_H__
#include "drmP.h"
#include "nouveau_drv.h"
#include "nv04_display.h"
#include <subdev/bios/pll.h>
......@@ -60,37 +59,41 @@ extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp,
static inline uint32_t NVReadCRTC(struct drm_device *dev,
int head, uint32_t reg)
{
struct nouveau_device *device = nouveau_dev(dev);
uint32_t val;
if (head)
reg += NV_PCRTC0_SIZE;
val = nv_rd32(dev, reg);
val = nv_rd32(device, reg);
return val;
}
static inline void NVWriteCRTC(struct drm_device *dev,
int head, uint32_t reg, uint32_t val)
{
struct nouveau_device *device = nouveau_dev(dev);
if (head)
reg += NV_PCRTC0_SIZE;
nv_wr32(dev, reg, val);
nv_wr32(device, reg, val);
}
static inline uint32_t NVReadRAMDAC(struct drm_device *dev,
int head, uint32_t reg)
{
struct nouveau_device *device = nouveau_dev(dev);
uint32_t val;
if (head)
reg += NV_PRAMDAC0_SIZE;
val = nv_rd32(dev, reg);
val = nv_rd32(device, reg);
return val;
}
static inline void NVWriteRAMDAC(struct drm_device *dev,
int head, uint32_t reg, uint32_t val)
{
struct nouveau_device *device = nouveau_dev(dev);
if (head)
reg += NV_PRAMDAC0_SIZE;
nv_wr32(dev, reg, val);
nv_wr32(device, reg, val);
}
static inline uint8_t nv_read_tmds(struct drm_device *dev,
......@@ -116,16 +119,18 @@ static inline void nv_write_tmds(struct drm_device *dev,
static inline void NVWriteVgaCrtc(struct drm_device *dev,
int head, uint8_t index, uint8_t value)
{
nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
struct nouveau_device *device = nouveau_dev(dev);
nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
nv_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
}
static inline uint8_t NVReadVgaCrtc(struct drm_device *dev,
int head, uint8_t index)
{
struct nouveau_device *device = nouveau_dev(dev);
uint8_t val;
nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
val = nv_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
return val;
}
......@@ -159,68 +164,74 @@ static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_
static inline uint8_t NVReadPRMVIO(struct drm_device *dev,
int head, uint32_t reg)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_device *device = nouveau_dev(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
uint8_t val;
/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
* NVSetOwner for the relevant head to be programmed */
if (head && dev_priv->card_type == NV_40)
if (head && nv_device(drm->device)->card_type == NV_40)
reg += NV_PRMVIO_SIZE;
val = nv_rd08(dev, reg);
val = nv_rd08(device, reg);
return val;
}
static inline void NVWritePRMVIO(struct drm_device *dev,
int head, uint32_t reg, uint8_t value)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_device *device = nouveau_dev(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
* NVSetOwner for the relevant head to be programmed */
if (head && dev_priv->card_type == NV_40)
if (head && nv_device(drm->device)->card_type == NV_40)
reg += NV_PRMVIO_SIZE;
nv_wr08(dev, reg, value);
nv_wr08(device, reg, value);
}
static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable)
{
nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
struct nouveau_device *device = nouveau_dev(dev);
nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20);
}
static inline bool NVGetEnablePalette(struct drm_device *dev, int head)
{
nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
struct nouveau_device *device = nouveau_dev(dev);
nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
return !(nv_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20);
}
static inline void NVWriteVgaAttr(struct drm_device *dev,
int head, uint8_t index, uint8_t value)
{
struct nouveau_device *device = nouveau_dev(dev);
if (NVGetEnablePalette(dev, head))
index &= ~0x20;
else
index |= 0x20;
nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
nv_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
}
static inline uint8_t NVReadVgaAttr(struct drm_device *dev,
int head, uint8_t index)
{
struct nouveau_device *device = nouveau_dev(dev);
uint8_t val;
if (NVGetEnablePalette(dev, head))
index &= ~0x20;
else
index |= 0x20;
nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
val = nv_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
return val;
}
......@@ -247,10 +258,11 @@ static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect)
static inline bool
nv_heads_tied(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_device *device = nouveau_dev(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
if (dev_priv->chipset == 0x11)
return !!(nv_rd32(dev, NV_PBUS_DEBUG_1) & (1 << 28));
if (nv_device(drm->device)->chipset == 0x11)
return !!(nv_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28));
return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4;
}
......@@ -299,13 +311,13 @@ nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock)
static inline bool
NVLockVgaCrtcs(struct drm_device *dev, bool lock)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX);
NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX,
lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
/* NV11 has independently lockable extended crtcs, except when tied */
if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev))
if (nv_device(drm->device)->chipset == 0x11 && !nv_heads_tied(dev))
NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX,
lock ? NV_CIO_SR_LOCK_VALUE :
NV_CIO_SR_UNLOCK_RW_VALUE);
......@@ -320,9 +332,9 @@ NVLockVgaCrtcs(struct drm_device *dev, bool lock)
static inline int nv_cursor_width(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
return nv_device(drm->device)->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
}
static inline void
......@@ -340,11 +352,11 @@ nv_fix_nv40_hw_cursor(struct drm_device *dev, int head)
static inline void
nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
NVWriteCRTC(dev, head, NV_PCRTC_START, offset);
if (dev_priv->card_type == NV_04) {
if (nv_device(drm->device)->card_type == NV_04) {
/*
* Hilarious, the 24th bit doesn't want to stick to
* PCRTC_START...
......@@ -359,7 +371,7 @@ nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset)
static inline void
nv_show_cursor(struct drm_device *dev, int head, bool show)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
uint8_t *curctl1 =
&nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX];
......@@ -369,14 +381,14 @@ nv_show_cursor(struct drm_device *dev, int head, bool show)
*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
if (dev_priv->card_type == NV_40)
if (nv_device(drm->device)->card_type == NV_40)
nv_fix_nv40_hw_cursor(dev, head);
}
static inline uint32_t
nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_drm *drm = nouveau_drm(dev);
int mask;
if (bpp == 15)
......@@ -385,7 +397,7 @@ nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp)
bpp = 8;
/* Alignment requirements taken from the Haiku driver */
if (dev_priv->card_type == NV_04)
if (nv_device(drm->device)->card_type == NV_04)
mask = 128 / bpp - 1;
else
mask = 512 / bpp - 1;
......
#ifndef __NOUVEAU_IRQ_H__
#define __NOUVEAU_IRQ_H__
extern int nouveau_irq_init(struct drm_device *);
extern void nouveau_irq_fini(struct drm_device *);
extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
extern void nouveau_irq_preinstall(struct drm_device *);
extern int nouveau_irq_postinstall(struct drm_device *);
extern void nouveau_irq_uninstall(struct drm_device *);
#endif
......@@ -22,13 +22,13 @@
* Authors: Dave Airlie
*/
#include <linux/dma-buf.h>
#include "drmP.h"
#include "drm.h"
#include "nouveau_drv.h"
#include <nouveau_drm.h>
#include <linux/dma-buf.h>
#include "nouveau_drm.h"
#include "nouveau_gem.h"
static struct sg_table *nouveau_gem_map_dma_buf(struct dma_buf_attachment *attachment,
enum dma_data_direction dir)
......
#include "nouveau_revcompat.h"
#include "nouveau_drv.h"
#include "nv50_display.h"
struct nouveau_drm *
nouveau_newpriv(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
return dev_priv->newpriv;
}
struct nouveau_bo *
nv50sema(struct drm_device *dev, int crtc)
{
return nv50_display(dev)->crtc[crtc].sem.bo;
}
struct nouveau_bo *
nvd0sema(struct drm_device *dev, int crtc)
{
return nvd0_display_crtc_sema(dev, crtc);
}
#ifndef __NOUVEAU_REVCOMPAT_H__
#define __NOUVEAU_REVCOMPAT_H__
#include "drmP.h"
struct nouveau_drm *
nouveau_newpriv(struct drm_device *);
struct nouveau_bo *nv50sema(struct drm_device *dev, int crtc);
struct nouveau_bo *nvd0sema(struct drm_device *dev, int crtc);
#endif
此差异已折叠。
......@@ -265,7 +265,7 @@ int
nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *file_priv = filp->private_data;
struct nouveau_drm *drm = nouveau_newpriv(file_priv->minor->dev);
struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev);
if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
return drm_mmap(filp, vma);
......
......@@ -17,5 +17,9 @@ struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *,
int nouveau_ttm_init(struct nouveau_drm *drm);
void nouveau_ttm_fini(struct nouveau_drm *drm);
int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
int nouveau_ttm_global_init(struct nouveau_drm *);
void nouveau_ttm_global_release(struct nouveau_drm *);
#endif
此差异已折叠。
#ifndef __NOUVEAU_VGA_H__
#define __NOUVEAU_VGA_H__
void nouveau_vga_init(struct nouveau_drm *);
void nouveau_vga_fini(struct nouveau_drm *);
void nouveau_vga_lastclose(struct drm_device *dev);
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -130,12 +130,14 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder);
static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg,
uint32_t val)
{
nv_wr32(dev, reg, val);
struct nouveau_device *device = nouveau_dev(dev);
nv_wr32(device, reg, val);
}
static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg)
{
return nv_rd32(dev, reg);
struct nouveau_device *device = nouveau_dev(dev);
return nv_rd32(device, reg);
}
static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册