Commit d6486813 authored by Dave Airlie's avatar Dave Airlie

Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-core-next

* 'nouveau/for-airlied' of ../drm-nouveau-next: (77 commits)
  drm/nouveau: set TASK_(UN)INTERRUPTIBLE before schedule_timeout()
  drm/nv50: fix some not-error error messages
  drm/nouveau: introduce gpio engine
  drm/nv50: correct wait condition for instmem flush
  drm/nouveau: Fix TV-out detection on unposted cards lacking a usable DCB table.
  drm/nouveau: Get rid of the remaining VGA CRTC locking.
  drm/nouveau: Move display init to a new nouveau_engine.
  drm/nouveau: Put back the old 2-messages I2C slave test.
  drm/nouveau: Reset AGP before running the init scripts.
  drm/nv30: Init the PFB+0x3xx memory timing regs.
  drm/nouveau: disable hotplug detect around DP link training
  drm/nv50: add function to control GPIO IRQ reporting
  drm/nouveau: add nv_mask register accessor
  drm/nouveau: fix build without CONFIG_ACPI
  drm/nouveau: Reset CRTC owner to 0 before BIOS init.
  drm/nouveau: No need to lock/unlock the VGA CRTC regs all the time.
  drm/nouveau: Remove useless CRTC_OWNER logging.
  drm/nouveau: Add some generic I2C gadget detection code.
  drm/i2c/ch7006: Don't assume that the specified config points to static memory.
  drm/nv04-nv3x: Implement init-compute-mem.
  ...

Conflicts:
	drivers/gpu/drm/nouveau/nouveau_bios.c
parents 78276271 05991110
...@@ -33,7 +33,7 @@ static void ch7006_encoder_set_config(struct drm_encoder *encoder, ...@@ -33,7 +33,7 @@ static void ch7006_encoder_set_config(struct drm_encoder *encoder,
{ {
struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder);
priv->params = params; priv->params = *(struct ch7006_encoder_params *)params;
} }
static void ch7006_encoder_destroy(struct drm_encoder *encoder) static void ch7006_encoder_destroy(struct drm_encoder *encoder)
...@@ -114,7 +114,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder, ...@@ -114,7 +114,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
{ {
struct i2c_client *client = drm_i2c_encoder_get_client(encoder); struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
struct ch7006_priv *priv = to_ch7006_priv(encoder); struct ch7006_priv *priv = to_ch7006_priv(encoder);
struct ch7006_encoder_params *params = priv->params; struct ch7006_encoder_params *params = &priv->params;
struct ch7006_state *state = &priv->state; struct ch7006_state *state = &priv->state;
uint8_t *regs = state->regs; uint8_t *regs = state->regs;
struct ch7006_mode *mode = priv->mode; struct ch7006_mode *mode = priv->mode;
...@@ -428,6 +428,22 @@ static int ch7006_remove(struct i2c_client *client) ...@@ -428,6 +428,22 @@ static int ch7006_remove(struct i2c_client *client)
return 0; return 0;
} }
static int ch7006_suspend(struct i2c_client *client, pm_message_t mesg)
{
ch7006_dbg(client, "\n");
return 0;
}
static int ch7006_resume(struct i2c_client *client)
{
ch7006_dbg(client, "\n");
ch7006_write(client, 0x3d, 0x0);
return 0;
}
static int ch7006_encoder_init(struct i2c_client *client, static int ch7006_encoder_init(struct i2c_client *client,
struct drm_device *dev, struct drm_device *dev,
struct drm_encoder_slave *encoder) struct drm_encoder_slave *encoder)
...@@ -487,6 +503,8 @@ static struct drm_i2c_encoder_driver ch7006_driver = { ...@@ -487,6 +503,8 @@ static struct drm_i2c_encoder_driver ch7006_driver = {
.i2c_driver = { .i2c_driver = {
.probe = ch7006_probe, .probe = ch7006_probe,
.remove = ch7006_remove, .remove = ch7006_remove,
.suspend = ch7006_suspend,
.resume = ch7006_resume,
.driver = { .driver = {
.name = "ch7006", .name = "ch7006",
......
...@@ -77,7 +77,7 @@ struct ch7006_state { ...@@ -77,7 +77,7 @@ struct ch7006_state {
}; };
struct ch7006_priv { struct ch7006_priv {
struct ch7006_encoder_params *params; struct ch7006_encoder_params params;
struct ch7006_mode *mode; struct ch7006_mode *mode;
struct ch7006_state state; struct ch7006_state state;
......
...@@ -9,10 +9,10 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ ...@@ -9,10 +9,10 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
nouveau_dp.o nouveau_grctx.o \ nouveau_dp.o \
nv04_timer.o \ nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \ nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
nv04_graph.o nv10_graph.o nv20_graph.o \ nv04_graph.o nv10_graph.o nv20_graph.o \
nv40_graph.o nv50_graph.o \ nv40_graph.o nv50_graph.o \
...@@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ ...@@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv50_cursor.o nv50_display.o nv50_fbcon.o \ nv50_cursor.o nv50_display.o nv50_fbcon.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
nv17_gpio.o nv50_gpio.o \ nv10_gpio.o nv50_gpio.o \
nv50_calc.o nv50_calc.o
nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <acpi/acpi_drivers.h> #include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <acpi/video.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
...@@ -11,6 +12,7 @@ ...@@ -11,6 +12,7 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
#include "nv50_display.h" #include "nv50_display.h"
#include "nouveau_connector.h"
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
...@@ -42,7 +44,7 @@ static const char nouveau_dsm_muid[] = { ...@@ -42,7 +44,7 @@ static const char nouveau_dsm_muid[] = {
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
}; };
static int nouveau_dsm(acpi_handle handle, int func, int arg, int *result) static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
{ {
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_object_list input; struct acpi_object_list input;
...@@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) ...@@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
{ {
return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len); return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
} }
int
nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct acpi_device *acpidev;
acpi_handle handle;
int type, ret;
void *edid;
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_LVDS:
case DRM_MODE_CONNECTOR_eDP:
type = ACPI_VIDEO_DISPLAY_LCD;
break;
default:
return -EINVAL;
}
handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
if (!handle)
return -ENODEV;
ret = acpi_bus_get_device(handle, &acpidev);
if (ret)
return -ENODEV;
ret = acpi_video_get_edid(acpidev, type, -1, &edid);
if (ret < 0)
return ret;
nv_connector->edid = edid;
return 0;
}
This diff is collapsed.
...@@ -81,6 +81,7 @@ struct dcb_connector_table_entry { ...@@ -81,6 +81,7 @@ struct dcb_connector_table_entry {
enum dcb_connector_type type; enum dcb_connector_type type;
uint8_t index2; uint8_t index2;
uint8_t gpio_tag; uint8_t gpio_tag;
void *drm;
}; };
struct dcb_connector_table { struct dcb_connector_table {
...@@ -117,6 +118,7 @@ struct dcb_entry { ...@@ -117,6 +118,7 @@ struct dcb_entry {
struct { struct {
struct sor_conf sor; struct sor_conf sor;
bool use_straps_for_mode; bool use_straps_for_mode;
bool use_acpi_for_edid;
bool use_power_scripts; bool use_power_scripts;
} lvdsconf; } lvdsconf;
struct { struct {
...@@ -249,8 +251,6 @@ struct nvbios { ...@@ -249,8 +251,6 @@ struct nvbios {
struct { struct {
int crtchead; int crtchead;
/* these need remembering across suspend */
uint32_t saved_nv_pfb_cfg0;
} state; } state;
struct { struct {
......
...@@ -461,9 +461,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, ...@@ -461,9 +461,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
return ret; return ret;
ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
evict, no_wait_reserve, no_wait_gpu, new_mem); evict || (nvbo->channel &&
if (nvbo->channel && nvbo->channel != chan) nvbo->channel != chan),
ret = nouveau_fence_wait(fence, NULL, false, false); no_wait_reserve, no_wait_gpu, new_mem);
nouveau_fence_unref((void *)&fence); nouveau_fence_unref((void *)&fence);
return ret; return ret;
} }
...@@ -711,8 +711,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, ...@@ -711,8 +711,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
return ret; return ret;
/* Software copy if the card isn't up and running yet. */ /* Software copy if the card isn't up and running yet. */
if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || if (!dev_priv->channel) {
!dev_priv->channel) {
ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
goto out; goto out;
} }
......
...@@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, ...@@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
struct nv_sim_state sim_data; struct nv_sim_state sim_data;
int MClk = nouveau_hw_get_clock(dev, MPLL); int MClk = nouveau_hw_get_clock(dev, MPLL);
int NVClk = nouveau_hw_get_clock(dev, NVPLL); int NVClk = nouveau_hw_get_clock(dev, NVPLL);
uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1); uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1);
sim_data.pclk_khz = VClk; sim_data.pclk_khz = VClk;
sim_data.mclk_khz = MClk; sim_data.mclk_khz = MClk;
...@@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, ...@@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
sim_data.mem_latency = 3; sim_data.mem_latency = 3;
sim_data.mem_page_miss = 10; sim_data.mem_page_miss = 10;
} else { } else {
sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1; sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1;
sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
sim_data.mem_latency = cfg1 & 0xf; sim_data.mem_latency = cfg1 & 0xf;
sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
......
...@@ -258,9 +258,7 @@ nouveau_channel_free(struct nouveau_channel *chan) ...@@ -258,9 +258,7 @@ nouveau_channel_free(struct nouveau_channel *chan)
nouveau_debugfs_channel_fini(chan); nouveau_debugfs_channel_fini(chan);
/* Give outstanding push buffers a chance to complete */ /* Give outstanding push buffers a chance to complete */
spin_lock_irqsave(&chan->fence.lock, flags);
nouveau_fence_update(chan); nouveau_fence_update(chan);
spin_unlock_irqrestore(&chan->fence.lock, flags);
if (chan->fence.sequence != chan->fence.sequence_ack) { if (chan->fence.sequence != chan->fence.sequence_ack) {
struct nouveau_fence *fence = NULL; struct nouveau_fence *fence = NULL;
...@@ -369,8 +367,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, ...@@ -369,8 +367,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
struct nouveau_channel *chan; struct nouveau_channel *chan;
int ret; int ret;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
if (dev_priv->engine.graph.accel_blocked) if (dev_priv->engine.graph.accel_blocked)
return -ENODEV; return -ENODEV;
...@@ -419,7 +415,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, ...@@ -419,7 +415,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
struct drm_nouveau_channel_free *cfree = data; struct drm_nouveau_channel_free *cfree = data;
struct nouveau_channel *chan; struct nouveau_channel *chan;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
nouveau_channel_free(chan); nouveau_channel_free(chan);
......
This diff is collapsed.
...@@ -49,7 +49,10 @@ static inline struct nouveau_connector *nouveau_connector( ...@@ -49,7 +49,10 @@ static inline struct nouveau_connector *nouveau_connector(
return container_of(con, struct nouveau_connector, base); return container_of(con, struct nouveau_connector, base);
} }
int nouveau_connector_create(struct drm_device *, struct drm_connector *
struct dcb_connector_table_entry *); nouveau_connector_create(struct drm_device *, int index);
void
nouveau_connector_set_polling(struct drm_connector *);
#endif /* __NOUVEAU_CONNECTOR_H__ */ #endif /* __NOUVEAU_CONNECTOR_H__ */
...@@ -92,11 +92,9 @@ nouveau_dma_init(struct nouveau_channel *chan) ...@@ -92,11 +92,9 @@ nouveau_dma_init(struct nouveau_channel *chan)
return ret; return ret;
/* Map M2MF notifier object - fbcon. */ /* Map M2MF notifier object - fbcon. */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = nouveau_bo_map(chan->notifier_bo); ret = nouveau_bo_map(chan->notifier_bo);
if (ret) if (ret)
return ret; return ret;
}
/* Insert NOPS for NOUVEAU_DMA_SKIPS */ /* Insert NOPS for NOUVEAU_DMA_SKIPS */
ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
......
...@@ -23,8 +23,10 @@ ...@@ -23,8 +23,10 @@
*/ */
#include "drmP.h" #include "drmP.h"
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_i2c.h" #include "nouveau_i2c.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h" #include "nouveau_encoder.h"
static int static int
...@@ -270,13 +272,39 @@ bool ...@@ -270,13 +272,39 @@ bool
nouveau_dp_link_train(struct drm_encoder *encoder) nouveau_dp_link_train(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
uint8_t config[4]; struct nouveau_connector *nv_connector;
uint8_t status[3]; struct bit_displayport_encoder_table *dpe;
int dpe_headerlen;
uint8_t config[4], status[3];
bool cr_done, cr_max_vs, eq_done; bool cr_done, cr_max_vs, eq_done;
int ret = 0, i, tries, voltage; int ret = 0, i, tries, voltage;
NV_DEBUG_KMS(dev, "link training!!\n"); NV_DEBUG_KMS(dev, "link training!!\n");
nv_connector = nouveau_encoder_connector_get(nv_encoder);
if (!nv_connector)
return false;
dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
if (!dpe) {
NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
return false;
}
/* disable hotplug detect, this flips around on some panels during
* link training.
*/
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
if (dpe->script0) {
NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
nv_encoder->dcb);
}
train: train:
cr_done = eq_done = false; cr_done = eq_done = false;
...@@ -403,6 +431,15 @@ nouveau_dp_link_train(struct drm_encoder *encoder) ...@@ -403,6 +431,15 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
} }
} }
if (dpe->script1) {
NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
nv_encoder->dcb);
}
/* re-enable hotplug detect */
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
return eq_done; return eq_done;
} }
......
...@@ -35,10 +35,6 @@ ...@@ -35,10 +35,6 @@
#include "drm_pciids.h" #include "drm_pciids.h"
MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)");
int nouveau_ctxfw = 0;
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
MODULE_PARM_DESC(noagp, "Disable AGP"); MODULE_PARM_DESC(noagp, "Disable AGP");
int nouveau_noagp; int nouveau_noagp;
module_param_named(noagp, nouveau_noagp, int, 0400); module_param_named(noagp, nouveau_noagp, int, 0400);
...@@ -56,7 +52,7 @@ int nouveau_vram_pushbuf; ...@@ -56,7 +52,7 @@ int nouveau_vram_pushbuf;
module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
int nouveau_vram_notify = 1; int nouveau_vram_notify = 0;
module_param_named(vram_notify, nouveau_vram_notify, int, 0400); module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
...@@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) ...@@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
struct drm_crtc *crtc; struct drm_crtc *crtc;
int ret, i; int ret, i;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
if (pm_state.event == PM_EVENT_PRETHAW) if (pm_state.event == PM_EVENT_PRETHAW)
return 0; return 0;
...@@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev) ...@@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
struct drm_crtc *crtc; struct drm_crtc *crtc;
int ret, i; int ret, i;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
nouveau_fbcon_save_disable_accel(dev); nouveau_fbcon_save_disable_accel(dev);
NV_INFO(dev, "We're back, enabling device...\n"); NV_INFO(dev, "We're back, enabling device...\n");
...@@ -269,6 +259,13 @@ nouveau_pci_resume(struct pci_dev *pdev) ...@@ -269,6 +259,13 @@ nouveau_pci_resume(struct pci_dev *pdev)
return -1; return -1;
pci_set_master(dev->pdev); pci_set_master(dev->pdev);
/* Make sure the AGP controller is in a consistent state */
if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
nouveau_mem_reset_agp(dev);
/* Make the CRTCs accessible */
engine->display.early_init(dev);
NV_INFO(dev, "POSTing device...\n"); NV_INFO(dev, "POSTing device...\n");
ret = nouveau_run_vbios_init(dev); ret = nouveau_run_vbios_init(dev);
if (ret) if (ret)
...@@ -323,7 +320,6 @@ nouveau_pci_resume(struct pci_dev *pdev) ...@@ -323,7 +320,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
int ret;
ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
if (!ret) if (!ret)
...@@ -332,11 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev) ...@@ -332,11 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
NV_ERROR(dev, "Could not pin/map cursor.\n"); NV_ERROR(dev, "Could not pin/map cursor.\n");
} }
if (dev_priv->card_type < NV_50) { engine->display.init(dev);
nv04_display_restore(dev);
NVLockVgaCrtcs(dev, false);
} else
nv50_display_init(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
...@@ -371,7 +363,8 @@ nouveau_pci_resume(struct pci_dev *pdev) ...@@ -371,7 +363,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
static struct drm_driver driver = { static struct drm_driver driver = {
.driver_features = .driver_features =
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM, DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
DRIVER_MODESET,
.load = nouveau_load, .load = nouveau_load,
.firstopen = nouveau_firstopen, .firstopen = nouveau_firstopen,
.lastclose = nouveau_lastclose, .lastclose = nouveau_lastclose,
...@@ -438,16 +431,18 @@ static int __init nouveau_init(void) ...@@ -438,16 +431,18 @@ static int __init nouveau_init(void)
nouveau_modeset = 1; nouveau_modeset = 1;
} }
if (nouveau_modeset == 1) { if (!nouveau_modeset)
driver.driver_features |= DRIVER_MODESET; return 0;
nouveau_register_dsm_handler();
}
nouveau_register_dsm_handler();
return drm_init(&driver); return drm_init(&driver);
} }
static void __exit nouveau_exit(void) static void __exit nouveau_exit(void)
{ {
if (!nouveau_modeset)
return;
drm_exit(&driver); drm_exit(&driver);
nouveau_unregister_dsm_handler(); nouveau_unregister_dsm_handler();
} }
......
This diff is collapsed.
...@@ -38,13 +38,15 @@ struct nouveau_encoder { ...@@ -38,13 +38,15 @@ struct nouveau_encoder {
struct dcb_entry *dcb; struct dcb_entry *dcb;
int or; int or;
/* different to drm_encoder.crtc, this reflects what's
* actually programmed on the hw, not the proposed crtc */
struct drm_crtc *crtc;
struct drm_display_mode mode; struct drm_display_mode mode;
int last_dpms; int last_dpms;
struct nv04_output_reg restore; struct nv04_output_reg restore;
void (*disconnect)(struct nouveau_encoder *encoder);
union { union {
struct { struct {
int mc_unknown; int mc_unknown;
...@@ -71,8 +73,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) ...@@ -71,8 +73,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
struct nouveau_connector * struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder); nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry); int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry); int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
struct bit_displayport_encoder_table { struct bit_displayport_encoder_table {
uint32_t match; uint32_t match;
......
...@@ -333,7 +333,7 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev) ...@@ -333,7 +333,7 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev)
drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper); drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper);
} }
int static int
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
{ {
struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb; struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb;
......
...@@ -67,12 +67,13 @@ nouveau_fence_update(struct nouveau_channel *chan) ...@@ -67,12 +67,13 @@ nouveau_fence_update(struct nouveau_channel *chan)
if (USE_REFCNT) if (USE_REFCNT)
sequence = nvchan_rd32(chan, 0x48); sequence = nvchan_rd32(chan, 0x48);
else else
sequence = chan->fence.last_sequence_irq; sequence = atomic_read(&chan->fence.last_sequence_irq);
if (chan->fence.sequence_ack == sequence) if (chan->fence.sequence_ack == sequence)
return; return;
chan->fence.sequence_ack = sequence; chan->fence.sequence_ack = sequence;
spin_lock(&chan->fence.lock);
list_for_each_safe(entry, tmp, &chan->fence.pending) { list_for_each_safe(entry, tmp, &chan->fence.pending) {
fence = list_entry(entry, struct nouveau_fence, entry); fence = list_entry(entry, struct nouveau_fence, entry);
...@@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan) ...@@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan)
if (sequence == chan->fence.sequence_ack) if (sequence == chan->fence.sequence_ack)
break; break;
} }
spin_unlock(&chan->fence.lock);
} }
int int
...@@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence) ...@@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence)
{ {
struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private; struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private;
struct nouveau_channel *chan = fence->channel; struct nouveau_channel *chan = fence->channel;
unsigned long flags;
int ret; int ret;
ret = RING_SPACE(chan, 2); ret = RING_SPACE(chan, 2);
...@@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) ...@@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence)
return ret; return ret;
if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) { if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) {
spin_lock_irqsave(&chan->fence.lock, flags);
nouveau_fence_update(chan); nouveau_fence_update(chan);
spin_unlock_irqrestore(&chan->fence.lock, flags);
BUG_ON(chan->fence.sequence == BUG_ON(chan->fence.sequence ==
chan->fence.sequence_ack - 1); chan->fence.sequence_ack - 1);
...@@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence) ...@@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence)
fence->sequence = ++chan->fence.sequence; fence->sequence = ++chan->fence.sequence;
kref_get(&fence->refcount); kref_get(&fence->refcount);
spin_lock_irqsave(&chan->fence.lock, flags); spin_lock(&chan->fence.lock);
list_add_tail(&fence->entry, &chan->fence.pending); list_add_tail(&fence->entry, &chan->fence.pending);
spin_unlock_irqrestore(&chan->fence.lock, flags); spin_unlock(&chan->fence.lock);
BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
OUT_RING(chan, fence->sequence); OUT_RING(chan, fence->sequence);
...@@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg) ...@@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg)
{ {
struct nouveau_fence *fence = nouveau_fence(sync_obj); struct nouveau_fence *fence = nouveau_fence(sync_obj);
struct nouveau_channel *chan = fence->channel; struct nouveau_channel *chan = fence->channel;
unsigned long flags;
if (fence->signalled) if (fence->signalled)
return true; return true;
spin_lock_irqsave(&chan->fence.lock, flags);
nouveau_fence_update(chan); nouveau_fence_update(chan);
spin_unlock_irqrestore(&chan->fence.lock, flags);
return fence->signalled; return fence->signalled;
} }
...@@ -190,8 +186,6 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) ...@@ -190,8 +186,6 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
unsigned long timeout = jiffies + (3 * DRM_HZ); unsigned long timeout = jiffies + (3 * DRM_HZ);
int ret = 0; int ret = 0;
__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
while (1) { while (1) {
if (nouveau_fence_signalled(sync_obj, sync_arg)) if (nouveau_fence_signalled(sync_obj, sync_arg))
break; break;
...@@ -201,6 +195,8 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) ...@@ -201,6 +195,8 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
break; break;
} }
__set_current_state(intr ? TASK_INTERRUPTIBLE
: TASK_UNINTERRUPTIBLE);
if (lazy) if (lazy)
schedule_timeout(1); schedule_timeout(1);
...@@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg) ...@@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg)
return 0; return 0;
} }
void
nouveau_fence_handler(struct drm_device *dev, int channel)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_channel *chan = NULL;
if (channel >= 0 && channel < dev_priv->engine.fifo.channels)
chan = dev_priv->fifos[channel];
if (chan) {
spin_lock_irq(&chan->fence.lock);
nouveau_fence_update(chan);
spin_unlock_irq(&chan->fence.lock);
}
}
int int
nouveau_fence_init(struct nouveau_channel *chan) nouveau_fence_init(struct nouveau_channel *chan)
{ {
INIT_LIST_HEAD(&chan->fence.pending); INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock); spin_lock_init(&chan->fence.lock);
atomic_set(&chan->fence.last_sequence_irq, 0);
return 0; return 0;
} }
......
...@@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, ...@@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
uint32_t flags = 0; uint32_t flags = 0;
int ret = 0; int ret = 0;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
...@@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
struct drm_nouveau_gem_pushbuf_bo *bo; struct drm_nouveau_gem_pushbuf_bo *bo;
struct nouveau_channel *chan; struct nouveau_channel *chan;
struct validate_op op; struct validate_op op;
struct nouveau_fence *fence = 0; struct nouveau_fence *fence = NULL;
int i, j, ret = 0, do_reloc = 0; int i, j, ret = 0, do_reloc = 0;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
req->vram_available = dev_priv->fb_aper_free; req->vram_available = dev_priv->fb_aper_free;
...@@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, ...@@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
int ret = -EINVAL; int ret = -EINVAL;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
gem = drm_gem_object_lookup(dev, file_priv, req->handle); gem = drm_gem_object_lookup(dev, file_priv, req->handle);
if (!gem) if (!gem)
return ret; return ret;
...@@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, ...@@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
struct nouveau_bo *nvbo; struct nouveau_bo *nvbo;
int ret = -EINVAL; int ret = -EINVAL;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
gem = drm_gem_object_lookup(dev, file_priv, req->handle); gem = drm_gem_object_lookup(dev, file_priv, req->handle);
if (!gem) if (!gem)
return ret; return ret;
...@@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, ...@@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
struct drm_gem_object *gem; struct drm_gem_object *gem;
int ret; int ret;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
gem = drm_gem_object_lookup(dev, file_priv, req->handle); gem = drm_gem_object_lookup(dev, file_priv, req->handle);
if (!gem) if (!gem)
return -EINVAL; return -EINVAL;
......
/*
* Copyright 2009 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include <linux/firmware.h>
#include <linux/slab.h>
#include "drmP.h"
#include "nouveau_drv.h"
struct nouveau_ctxprog {
uint32_t signature;
uint8_t version;
uint16_t length;
uint32_t data[];
} __attribute__ ((packed));
struct nouveau_ctxvals {
uint32_t signature;
uint8_t version;
uint32_t length;
struct {
uint32_t offset;
uint32_t value;
} data[];
} __attribute__ ((packed));
int
nouveau_grctx_prog_load(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
const int chipset = dev_priv->chipset;
const struct firmware *fw;
const struct nouveau_ctxprog *cp;
const struct nouveau_ctxvals *cv;
char name[32];
int ret, i;
if (pgraph->accel_blocked)
return -ENODEV;
if (!pgraph->ctxprog) {
sprintf(name, "nouveau/nv%02x.ctxprog", chipset);
ret = request_firmware(&fw, name, &dev->pdev->dev);
if (ret) {
NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset);
return ret;
}
pgraph->ctxprog = kmemdup(fw->data, fw->size, GFP_KERNEL);
if (!pgraph->ctxprog) {
NV_ERROR(dev, "OOM copying ctxprog\n");
release_firmware(fw);
return -ENOMEM;
}
cp = pgraph->ctxprog;
if (le32_to_cpu(cp->signature) != 0x5043564e ||
cp->version != 0 ||
le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
NV_ERROR(dev, "ctxprog invalid\n");
release_firmware(fw);
nouveau_grctx_fini(dev);
return -EINVAL;
}
release_firmware(fw);
}
if (!pgraph->ctxvals) {
sprintf(name, "nouveau/nv%02x.ctxvals", chipset);
ret = request_firmware(&fw, name, &dev->pdev->dev);
if (ret) {
NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset);
nouveau_grctx_fini(dev);
return ret;
}
pgraph->ctxvals = kmemdup(fw->data, fw->size, GFP_KERNEL);
if (!pgraph->ctxvals) {
NV_ERROR(dev, "OOM copying ctxvals\n");
release_firmware(fw);
nouveau_grctx_fini(dev);
return -ENOMEM;
}
cv = (void *)pgraph->ctxvals;
if (le32_to_cpu(cv->signature) != 0x5643564e ||
cv->version != 0 ||
le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
NV_ERROR(dev, "ctxvals invalid\n");
release_firmware(fw);
nouveau_grctx_fini(dev);
return -EINVAL;
}
release_firmware(fw);
}
cp = pgraph->ctxprog;
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
for (i = 0; i < le16_to_cpu(cp->length); i++)
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
le32_to_cpu(cp->data[i]));
return 0;
}
void
nouveau_grctx_fini(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
if (pgraph->ctxprog) {
kfree(pgraph->ctxprog);
pgraph->ctxprog = NULL;
}
if (pgraph->ctxvals) {
kfree(pgraph->ctxprog);
pgraph->ctxvals = NULL;
}
}
void
nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
struct nouveau_ctxvals *cv = pgraph->ctxvals;
int i;
if (!cv)
return;
for (i = 0; i < le32_to_cpu(cv->length); i++)
nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
le32_to_cpu(cv->data[i].value));
}
...@@ -278,3 +278,45 @@ nouveau_i2c_find(struct drm_device *dev, int index) ...@@ -278,3 +278,45 @@ nouveau_i2c_find(struct drm_device *dev, int index)
return i2c->chan; return i2c->chan;
} }
bool
nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
{
uint8_t buf[] = { 0 };
struct i2c_msg msgs[] = {
{
.addr = addr,
.flags = 0,
.len = 1,
.buf = buf,
},
{
.addr = addr,
.flags = I2C_M_RD,
.len = 1,
.buf = buf,
}
};
return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
}
int
nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info, int index)
{
struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
int i;
NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
for (i = 0; info[i].addr; i++) {
if (nouveau_probe_i2c_addr(i2c, info[i].addr)) {
NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
return i;
}
}
NV_DEBUG(dev, "No devices found.\n");
return -ENODEV;
}
...@@ -45,6 +45,9 @@ struct nouveau_i2c_chan { ...@@ -45,6 +45,9 @@ struct nouveau_i2c_chan {
int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
int nouveau_i2c_identify(struct drm_device *dev, const char *what,
struct i2c_board_info *info, int index);
int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte,
uint8_t *read_byte); uint8_t *read_byte);
......
This diff is collapsed.
...@@ -55,7 +55,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) ...@@ -55,7 +55,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
if (ret) if (ret)
goto out_err; goto out_err;
ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size); ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
if (ret) if (ret)
goto out_err; goto out_err;
...@@ -80,7 +80,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan) ...@@ -80,7 +80,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
nouveau_bo_unpin(chan->notifier_bo); nouveau_bo_unpin(chan->notifier_bo);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
drm_gem_object_unreference_unlocked(chan->notifier_bo->gem); drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
nouveau_mem_takedown(&chan->notifier_heap); drm_mm_takedown(&chan->notifier_heap);
} }
static void static void
...@@ -90,7 +90,7 @@ nouveau_notifier_gpuobj_dtor(struct drm_device *dev, ...@@ -90,7 +90,7 @@ nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
NV_DEBUG(dev, "\n"); NV_DEBUG(dev, "\n");
if (gpuobj->priv) if (gpuobj->priv)
nouveau_mem_free_block(gpuobj->priv); drm_mm_put_block(gpuobj->priv);
} }
int int
...@@ -100,18 +100,13 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -100,18 +100,13 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *nobj = NULL; struct nouveau_gpuobj *nobj = NULL;
struct mem_block *mem; struct drm_mm_node *mem;
uint32_t offset; uint32_t offset;
int target, ret; int target, ret;
if (!chan->notifier_heap) { mem = drm_mm_search_free(&chan->notifier_heap, size, 0, 0);
NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n", if (mem)
chan->id); mem = drm_mm_get_block(mem, size, 0);
return -EINVAL;
}
mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0,
(struct drm_file *)-2, 0);
if (!mem) { if (!mem) {
NV_ERROR(dev, "Channel %d notifier block full\n", chan->id); NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
return -ENOMEM; return -ENOMEM;
...@@ -144,7 +139,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -144,7 +139,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
mem->size, NV_DMA_ACCESS_RW, target, mem->size, NV_DMA_ACCESS_RW, target,
&nobj); &nobj);
if (ret) { if (ret) {
nouveau_mem_free_block(mem); drm_mm_put_block(mem);
NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret); NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret);
return ret; return ret;
} }
...@@ -154,7 +149,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -154,7 +149,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL); ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL);
if (ret) { if (ret) {
nouveau_gpuobj_del(dev, &nobj); nouveau_gpuobj_del(dev, &nobj);
nouveau_mem_free_block(mem); drm_mm_put_block(mem);
NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret); NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret);
return ret; return ret;
} }
...@@ -170,7 +165,7 @@ nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset) ...@@ -170,7 +165,7 @@ nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset)
return -EINVAL; return -EINVAL;
if (poffset) { if (poffset) {
struct mem_block *mem = nobj->priv; struct drm_mm_node *mem = nobj->priv;
if (*poffset >= mem->size) if (*poffset >= mem->size)
return false; return false;
...@@ -189,7 +184,6 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data, ...@@ -189,7 +184,6 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
struct nouveau_channel *chan; struct nouveau_channel *chan;
int ret; int ret;
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset);
......
This diff is collapsed.
#define NV04_PFB_BOOT_0 0x00100000
# define NV04_PFB_BOOT_0_RAM_AMOUNT 0x00000003
# define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB 0x00000000
# define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB 0x00000001
# define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB 0x00000002
# define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB 0x00000003
# define NV04_PFB_BOOT_0_RAM_WIDTH_128 0x00000004
# define NV04_PFB_BOOT_0_RAM_TYPE 0x00000028
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT 0x00000000
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT 0x00000008
# define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK 0x00000010
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT 0x00000018
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT 0x00000020
# define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16 0x00000028
# define NV04_PFB_BOOT_0_UMA_ENABLE 0x00000100
# define NV04_PFB_BOOT_0_UMA_SIZE 0x0000f000
#define NV04_PFB_DEBUG_0 0x00100080
# define NV04_PFB_DEBUG_0_PAGE_MODE 0x00000001
# define NV04_PFB_DEBUG_0_REFRESH_OFF 0x00000010
# define NV04_PFB_DEBUG_0_REFRESH_COUNTX64 0x00003f00
# define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK 0x00004000
# define NV04_PFB_DEBUG_0_SAFE_MODE 0x00008000
# define NV04_PFB_DEBUG_0_ALOM_ENABLE 0x00010000
# define NV04_PFB_DEBUG_0_CASOE 0x00100000
# define NV04_PFB_DEBUG_0_CKE_INVERT 0x10000000
# define NV04_PFB_DEBUG_0_REFINC 0x20000000
# define NV04_PFB_DEBUG_0_SAVE_POWER_OFF 0x40000000
#define NV04_PFB_CFG0 0x00100200
# define NV04_PFB_CFG0_SCRAMBLE 0x20000000
#define NV04_PFB_CFG1 0x00100204
#define NV04_PFB_FIFO_DATA 0x0010020c
# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000
# define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20
#define NV10_PFB_REFCTRL 0x00100210
# define NV10_PFB_REFCTRL_VALID_1 (1 << 31)
#define NV04_PFB_PAD 0x0010021c
# define NV04_PFB_PAD_CKE_NORMAL (1 << 0)
#define NV10_PFB_TILE(i) (0x00100240 + (i*16))
#define NV10_PFB_TILE__SIZE 8
#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16))
#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16))
#define NV10_PFB_TSTATUS(i) (0x0010024c + (i*16))
#define NV04_PFB_REF 0x001002d0
# define NV04_PFB_REF_CMD_REFRESH (1 << 0)
#define NV04_PFB_PRE 0x001002d4
# define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0)
#define NV10_PFB_CLOSE_PAGE2 0x0010033c
#define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i))
#define NV40_PFB_TILE(i) (0x00100600 + (i*16))
#define NV40_PFB_TILE__SIZE_0 12
#define NV40_PFB_TILE__SIZE_1 15
#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16))
#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16))
#define NV40_PFB_TSTATUS(i) (0x0010060c + (i*16))
#define NV40_PFB_UNK_800 0x00100800
#define NV03_BOOT_0 0x00100000 #define NV_PEXTDEV_BOOT_0 0x00101000
# define NV03_BOOT_0_RAM_AMOUNT 0x00000003 #define NV_PEXTDEV_BOOT_0_RAMCFG 0x0000003c
# define NV03_BOOT_0_RAM_AMOUNT_8MB 0x00000000 # define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12)
# define NV03_BOOT_0_RAM_AMOUNT_2MB 0x00000001 #define NV_PEXTDEV_BOOT_3 0x0010100c
# define NV03_BOOT_0_RAM_AMOUNT_4MB 0x00000002
# define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM 0x00000003
# define NV04_BOOT_0_RAM_AMOUNT_32MB 0x00000000
# define NV04_BOOT_0_RAM_AMOUNT_4MB 0x00000001
# define NV04_BOOT_0_RAM_AMOUNT_8MB 0x00000002
# define NV04_BOOT_0_RAM_AMOUNT_16MB 0x00000003
#define NV04_FIFO_DATA 0x0010020c
# define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK 0xfff00000
# define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT 20
#define NV_RAMIN 0x00700000 #define NV_RAMIN 0x00700000
...@@ -131,23 +176,6 @@ ...@@ -131,23 +176,6 @@
#define NV04_PTIMER_TIME_1 0x00009410 #define NV04_PTIMER_TIME_1 0x00009410
#define NV04_PTIMER_ALARM_0 0x00009420 #define NV04_PTIMER_ALARM_0 0x00009420
#define NV04_PFB_CFG0 0x00100200
#define NV04_PFB_CFG1 0x00100204
#define NV40_PFB_020C 0x0010020C
#define NV10_PFB_TILE(i) (0x00100240 + (i*16))
#define NV10_PFB_TILE__SIZE 8
#define NV10_PFB_TLIMIT(i) (0x00100244 + (i*16))
#define NV10_PFB_TSIZE(i) (0x00100248 + (i*16))
#define NV10_PFB_TSTATUS(i) (0x0010024C + (i*16))
#define NV10_PFB_CLOSE_PAGE2 0x0010033C
#define NV40_PFB_TILE(i) (0x00100600 + (i*16))
#define NV40_PFB_TILE__SIZE_0 12
#define NV40_PFB_TILE__SIZE_1 15
#define NV40_PFB_TLIMIT(i) (0x00100604 + (i*16))
#define NV40_PFB_TSIZE(i) (0x00100608 + (i*16))
#define NV40_PFB_TSTATUS(i) (0x0010060C + (i*16))
#define NV40_PFB_UNK_800 0x00100800
#define NV04_PGRAPH_DEBUG_0 0x00400080 #define NV04_PGRAPH_DEBUG_0 0x00400080
#define NV04_PGRAPH_DEBUG_1 0x00400084 #define NV04_PGRAPH_DEBUG_1 0x00400084
#define NV04_PGRAPH_DEBUG_2 0x00400088 #define NV04_PGRAPH_DEBUG_2 0x00400088
...@@ -814,6 +842,7 @@ ...@@ -814,6 +842,7 @@
#define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000 #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE 0x80000000
#define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL 0x00000fff
#define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80) #define NV50_SOR_DP_CTRL(i,l) (0x0061c10c + (i) * 0x800 + (l) * 0x80)
#define NV50_SOR_DP_CTRL_ENABLED 0x00000001
#define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000 #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED 0x00004000
#define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000 #define NV50_SOR_DP_CTRL_LANE_MASK 0x001f0000
#define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000 #define NV50_SOR_DP_CTRL_LANE_0_ENABLED 0x00010000
......
...@@ -97,7 +97,6 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ...@@ -97,7 +97,6 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start); NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start);
dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT); pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT);
nvbe->pte_start = pte; nvbe->pte_start = pte;
for (i = 0; i < nvbe->nr_pages; i++) { for (i = 0; i < nvbe->nr_pages; i++) {
...@@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) ...@@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
dma_offset += NV_CTXDMA_PAGE_SIZE; dma_offset += NV_CTXDMA_PAGE_SIZE;
} }
} }
dev_priv->engine.instmem.finish_access(nvbe->dev); dev_priv->engine.instmem.flush(nvbe->dev);
if (dev_priv->card_type == NV_50) { if (dev_priv->card_type == NV_50) {
nv_wr32(dev, 0x100c80, 0x00050001); nv50_vm_flush(dev, 5); /* PGRAPH */
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { nv50_vm_flush(dev, 0); /* PFIFO */
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
nv_rd32(dev, 0x100c80));
return -EBUSY;
}
nv_wr32(dev, 0x100c80, 0x00000001);
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
nv_rd32(dev, 0x100c80));
return -EBUSY;
}
} }
nvbe->bound = true; nvbe->bound = true;
...@@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be) ...@@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
if (!nvbe->bound) if (!nvbe->bound)
return 0; return 0;
dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
pte = nvbe->pte_start; pte = nvbe->pte_start;
for (i = 0; i < nvbe->nr_pages; i++) { for (i = 0; i < nvbe->nr_pages; i++) {
dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
...@@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be) ...@@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
dma_offset += NV_CTXDMA_PAGE_SIZE; dma_offset += NV_CTXDMA_PAGE_SIZE;
} }
} }
dev_priv->engine.instmem.finish_access(nvbe->dev); dev_priv->engine.instmem.flush(nvbe->dev);
if (dev_priv->card_type == NV_50) { if (dev_priv->card_type == NV_50) {
nv_wr32(dev, 0x100c80, 0x00050001); nv50_vm_flush(dev, 5);
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { nv50_vm_flush(dev, 0);
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
nv_rd32(dev, 0x100c80));
return -EBUSY;
}
nv_wr32(dev, 0x100c80, 0x00000001);
if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
NV_ERROR(dev, "0x100c80 = 0x%08x\n",
nv_rd32(dev, 0x100c80));
return -EBUSY;
}
} }
nvbe->bound = false; nvbe->bound = false;
...@@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev) ...@@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev)
pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
dev_priv->engine.instmem.prepare_access(dev, true);
if (dev_priv->card_type < NV_50) { if (dev_priv->card_type < NV_50) {
/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
* confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE
...@@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev) ...@@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev)
nv_wo32(dev, gpuobj, (i+4)/4, 0); nv_wo32(dev, gpuobj, (i+4)/4, 0);
} }
} }
dev_priv->engine.instmem.finish_access(dev); dev_priv->engine.instmem.flush(dev);
dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; dev_priv->gart_info.type = NOUVEAU_GART_SGDMA;
dev_priv->gart_info.aper_base = 0; dev_priv->gart_info.aper_base = 0;
...@@ -325,14 +296,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) ...@@ -325,14 +296,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
int pte; int pte;
pte = (offset >> NV_CTXDMA_PAGE_SHIFT); pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
if (dev_priv->card_type < NV_50) { if (dev_priv->card_type < NV_50) {
instmem->prepare_access(dev, false);
*page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK; *page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
instmem->finish_access(dev);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -157,6 +157,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -157,6 +157,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
{ {
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_connector *connector;
unsigned char seq1 = 0, crtc17 = 0; unsigned char seq1 = 0, crtc17 = 0;
unsigned char crtc1A; unsigned char crtc1A;
...@@ -211,6 +212,10 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) ...@@ -211,6 +212,10 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
NVVgaSeqReset(dev, nv_crtc->index, false); NVVgaSeqReset(dev, nv_crtc->index, false);
NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
/* Update connector polling modes */
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
nouveau_connector_set_polling(connector);
} }
static bool static bool
......
...@@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) ...@@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
...@@ -251,22 +252,21 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) ...@@ -251,22 +252,21 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
} }
saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
msleep(4); msleep(4);
saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
head = (saved_routput & 0x100) >> 8; head = (saved_routput & 0x100) >> 8;
#if 0
/* if there's a spare crtc, using it will minimise flicker for the case /* if there's a spare crtc, using it will minimise flicker */
* where the in-use crtc is in use by an off-chip tmds encoder */ if (!(NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX) & 0xC0))
if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled)
head ^= 1; head ^= 1;
#endif
/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
routput = (saved_routput & 0xfffffece) | head << 8; routput = (saved_routput & 0xfffffece) | head << 8;
...@@ -304,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) ...@@ -304,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
return sample; return sample;
} }
...@@ -315,9 +315,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -315,9 +315,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
uint32_t sample = nv17_dac_sample_load(encoder);
if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { if (nv04_dac_in_use(encoder))
return connector_status_disconnected;
if (nv17_dac_sample_load(encoder) &
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
NV_INFO(dev, "Load detected on output %c\n", NV_INFO(dev, "Load detected on output %c\n",
'@' + ffs(dcb->or)); '@' + ffs(dcb->or));
return connector_status_connected; return connector_status_connected;
...@@ -330,6 +333,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, ...@@ -330,6 +333,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
if (nv04_dac_in_use(encoder))
return false;
return true; return true;
} }
...@@ -428,6 +434,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) ...@@ -428,6 +434,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
} }
} }
/* Check if the DAC corresponding to 'encoder' is being used by
* someone else. */
bool nv04_dac_in_use(struct drm_encoder *encoder)
{
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
return nv_gf4_disp_arch(encoder->dev) &&
(dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index));
}
static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -501,11 +518,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = { ...@@ -501,11 +518,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
.destroy = nv04_dac_destroy, .destroy = nv04_dac_destroy,
}; };
int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) int
nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
{ {
const struct drm_encoder_helper_funcs *helper; const struct drm_encoder_helper_funcs *helper;
struct drm_encoder *encoder;
struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_encoder = NULL;
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder;
nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
if (!nv_encoder) if (!nv_encoder)
...@@ -527,5 +546,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry) ...@@ -527,5 +546,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
encoder->possible_crtcs = entry->heads; encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0; encoder->possible_clones = 0;
drm_mode_connector_attach_encoder(connector, encoder);
return 0; return 0;
} }
...@@ -413,10 +413,6 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) ...@@ -413,10 +413,6 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
struct dcb_entry *dcbe = nv_encoder->dcb; struct dcb_entry *dcbe = nv_encoder->dcb;
int head = nouveau_crtc(encoder->crtc)->index; int head = nouveau_crtc(encoder->crtc)->index;
NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
if (dcbe->type == OUTPUT_TMDS) if (dcbe->type == OUTPUT_TMDS)
run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
else if (dcbe->type == OUTPUT_LVDS) else if (dcbe->type == OUTPUT_LVDS)
...@@ -584,11 +580,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = { ...@@ -584,11 +580,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
.destroy = nv04_dfp_destroy, .destroy = nv04_dfp_destroy,
}; };
int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) int
nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry)
{ {
const struct drm_encoder_helper_funcs *helper; const struct drm_encoder_helper_funcs *helper;
struct drm_encoder *encoder;
struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_encoder = NULL;
struct drm_encoder *encoder;
int type; int type;
switch (entry->type) { switch (entry->type) {
...@@ -613,11 +610,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry) ...@@ -613,11 +610,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
nv_encoder->dcb = entry; nv_encoder->dcb = entry;
nv_encoder->or = ffs(entry->or) - 1; nv_encoder->or = ffs(entry->or) - 1;
drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type); drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type);
drm_encoder_helper_add(encoder, helper); drm_encoder_helper_add(encoder, helper);
encoder->possible_crtcs = entry->heads; encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0; encoder->possible_clones = 0;
drm_mode_connector_attach_encoder(connector, encoder);
return 0; return 0;
} }
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include "nouveau_encoder.h" #include "nouveau_encoder.h"
#include "nouveau_connector.h" #include "nouveau_connector.h"
#define MULTIPLE_ENCODERS(e) (e & (e - 1))
static void static void
nv04_display_store_initial_head_owner(struct drm_device *dev) nv04_display_store_initial_head_owner(struct drm_device *dev)
{ {
...@@ -41,7 +39,7 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) ...@@ -41,7 +39,7 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
if (dev_priv->chipset != 0x11) { if (dev_priv->chipset != 0x11) {
dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44); dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
goto ownerknown; return;
} }
/* reading CR44 is broken on nv11, so we attempt to infer it */ /* reading CR44 is broken on nv11, so we attempt to infer it */
...@@ -52,8 +50,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) ...@@ -52,8 +50,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
bool tvA = false; bool tvA = false;
bool tvB = false; bool tvB = false;
NVLockVgaCrtcs(dev, false);
slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) & slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
0x80; 0x80;
if (slaved_on_B) if (slaved_on_B)
...@@ -66,8 +62,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) ...@@ -66,8 +62,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) & tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
MASK(NV_CIO_CRE_LCD_LCD_SELECT)); MASK(NV_CIO_CRE_LCD_LCD_SELECT));
NVLockVgaCrtcs(dev, true);
if (slaved_on_A && !tvA) if (slaved_on_A && !tvA)
dev_priv->crtc_owner = 0x0; dev_priv->crtc_owner = 0x0;
else if (slaved_on_B && !tvB) else if (slaved_on_B && !tvB)
...@@ -79,14 +73,40 @@ nv04_display_store_initial_head_owner(struct drm_device *dev) ...@@ -79,14 +73,40 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
else else
dev_priv->crtc_owner = 0x0; dev_priv->crtc_owner = 0x0;
} }
}
int
nv04_display_early_init(struct drm_device *dev)
{
/* Make the I2C buses accessible. */
if (!nv_gf4_disp_arch(dev)) {
uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
if (!(pmc_enable & 1))
nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1);
}
ownerknown: /* Unlock the VGA CRTCs. */
NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner); NVLockVgaCrtcs(dev, false);
/* we need to ensure the heads are not tied henceforth, or reading any /* Make sure the CRTCs aren't in slaved mode. */
* 8 bit reg on head B will fail if (nv_two_heads(dev)) {
* setting a single arbitrary head solves that */ nv04_display_store_initial_head_owner(dev);
NVSetOwner(dev, 0); NVSetOwner(dev, 0);
}
return 0;
}
void
nv04_display_late_takedown(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
if (nv_two_heads(dev))
NVSetOwner(dev, dev_priv->crtc_owner);
NVLockVgaCrtcs(dev, true);
} }
int int
...@@ -94,14 +114,13 @@ nv04_display_create(struct drm_device *dev) ...@@ -94,14 +114,13 @@ nv04_display_create(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct dcb_table *dcb = &dev_priv->vbios.dcb; struct dcb_table *dcb = &dev_priv->vbios.dcb;
struct drm_connector *connector, *ct;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_crtc *crtc; struct drm_crtc *crtc;
int i, ret; int i, ret;
NV_DEBUG_KMS(dev, "\n"); NV_DEBUG_KMS(dev, "\n");
if (nv_two_heads(dev))
nv04_display_store_initial_head_owner(dev);
nouveau_hw_save_vga_fonts(dev, 1); nouveau_hw_save_vga_fonts(dev, 1);
drm_mode_config_init(dev); drm_mode_config_init(dev);
...@@ -132,19 +151,23 @@ nv04_display_create(struct drm_device *dev) ...@@ -132,19 +151,23 @@ nv04_display_create(struct drm_device *dev)
for (i = 0; i < dcb->entries; i++) { for (i = 0; i < dcb->entries; i++) {
struct dcb_entry *dcbent = &dcb->entry[i]; struct dcb_entry *dcbent = &dcb->entry[i];
connector = nouveau_connector_create(dev, dcbent->connector);
if (IS_ERR(connector))
continue;
switch (dcbent->type) { switch (dcbent->type) {
case OUTPUT_ANALOG: case OUTPUT_ANALOG:
ret = nv04_dac_create(dev, dcbent); ret = nv04_dac_create(connector, dcbent);
break; break;
case OUTPUT_LVDS: case OUTPUT_LVDS:
case OUTPUT_TMDS: case OUTPUT_TMDS:
ret = nv04_dfp_create(dev, dcbent); ret = nv04_dfp_create(connector, dcbent);
break; break;
case OUTPUT_TV: case OUTPUT_TV:
if (dcbent->location == DCB_LOC_ON_CHIP) if (dcbent->location == DCB_LOC_ON_CHIP)
ret = nv17_tv_create(dev, dcbent); ret = nv17_tv_create(connector, dcbent);
else else
ret = nv04_tv_create(dev, dcbent); ret = nv04_tv_create(connector, dcbent);
break; break;
default: default:
NV_WARN(dev, "DCB type %d not known\n", dcbent->type); NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
...@@ -155,12 +178,16 @@ nv04_display_create(struct drm_device *dev) ...@@ -155,12 +178,16 @@ nv04_display_create(struct drm_device *dev)
continue; continue;
} }
for (i = 0; i < dcb->connector.entries; i++) list_for_each_entry_safe(connector, ct,
nouveau_connector_create(dev, &dcb->connector.entry[i]); &dev->mode_config.connector_list, head) {
if (!connector->encoder_ids[0]) {
NV_WARN(dev, "%s has no encoders, removing\n",
drm_get_connector_name(connector));
connector->funcs->destroy(connector);
}
}
/* Save previous state */ /* Save previous state */
NVLockVgaCrtcs(dev, false);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
crtc->funcs->save(crtc); crtc->funcs->save(crtc);
...@@ -191,8 +218,6 @@ nv04_display_destroy(struct drm_device *dev) ...@@ -191,8 +218,6 @@ nv04_display_destroy(struct drm_device *dev)
} }
/* Restore state */ /* Restore state */
NVLockVgaCrtcs(dev, false);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
struct drm_encoder_helper_funcs *func = encoder->helper_private; struct drm_encoder_helper_funcs *func = encoder->helper_private;
...@@ -207,15 +232,12 @@ nv04_display_destroy(struct drm_device *dev) ...@@ -207,15 +232,12 @@ nv04_display_destroy(struct drm_device *dev)
nouveau_hw_save_vga_fonts(dev, 0); nouveau_hw_save_vga_fonts(dev, 0);
} }
void int
nv04_display_restore(struct drm_device *dev) nv04_display_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_crtc *crtc; struct drm_crtc *crtc;
NVLockVgaCrtcs(dev, false);
/* meh.. modeset apparently doesn't setup all the regs and depends /* meh.. modeset apparently doesn't setup all the regs and depends
* on pre-existing state, for now load the state of the card *before* * on pre-existing state, for now load the state of the card *before*
* nouveau was loaded, and then do a modeset. * nouveau was loaded, and then do a modeset.
...@@ -233,12 +255,6 @@ nv04_display_restore(struct drm_device *dev) ...@@ -233,12 +255,6 @@ nv04_display_restore(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
crtc->funcs->restore(crtc); crtc->funcs->restore(crtc);
if (nv_two_heads(dev)) { return 0;
NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n",
dev_priv->crtc_owner);
NVSetOwner(dev, dev_priv->crtc_owner);
}
NVLockVgaCrtcs(dev, true);
} }
...@@ -112,6 +112,12 @@ nv04_fifo_channel_id(struct drm_device *dev) ...@@ -112,6 +112,12 @@ nv04_fifo_channel_id(struct drm_device *dev)
NV03_PFIFO_CACHE1_PUSH1_CHID_MASK; NV03_PFIFO_CACHE1_PUSH1_CHID_MASK;
} }
#ifdef __BIG_ENDIAN
#define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN
#else
#define DMA_FETCH_ENDIANNESS 0
#endif
int int
nv04_fifo_create_context(struct nouveau_channel *chan) nv04_fifo_create_context(struct nouveau_channel *chan)
{ {
...@@ -131,18 +137,13 @@ nv04_fifo_create_context(struct nouveau_channel *chan) ...@@ -131,18 +137,13 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
spin_lock_irqsave(&dev_priv->context_switch_lock, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
/* Setup initial state */ /* Setup initial state */
dev_priv->engine.instmem.prepare_access(dev, true);
RAMFC_WR(DMA_PUT, chan->pushbuf_base); RAMFC_WR(DMA_PUT, chan->pushbuf_base);
RAMFC_WR(DMA_GET, chan->pushbuf_base); RAMFC_WR(DMA_GET, chan->pushbuf_base);
RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4); RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES | RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES | NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 | NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
#ifdef __BIG_ENDIAN DMA_FETCH_ENDIANNESS));
NV_PFIFO_CACHE1_BIG_ENDIAN |
#endif
0));
dev_priv->engine.instmem.finish_access(dev);
/* enable the fifo dma operation */ /* enable the fifo dma operation */
nv_wr32(dev, NV04_PFIFO_MODE, nv_wr32(dev, NV04_PFIFO_MODE,
...@@ -169,8 +170,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid) ...@@ -169,8 +170,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid)
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t fc = NV04_RAMFC(chid), tmp; uint32_t fc = NV04_RAMFC(chid), tmp;
dev_priv->engine.instmem.prepare_access(dev, false);
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
tmp = nv_ri32(dev, fc + 8); tmp = nv_ri32(dev, fc + 8);
...@@ -181,8 +180,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid) ...@@ -181,8 +180,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid)
nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20)); nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24)); nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
dev_priv->engine.instmem.finish_access(dev);
nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
} }
...@@ -223,7 +220,6 @@ nv04_fifo_unload_context(struct drm_device *dev) ...@@ -223,7 +220,6 @@ nv04_fifo_unload_context(struct drm_device *dev)
return -EINVAL; return -EINVAL;
} }
dev_priv->engine.instmem.prepare_access(dev, true);
RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16; tmp = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
...@@ -233,7 +229,6 @@ nv04_fifo_unload_context(struct drm_device *dev) ...@@ -233,7 +229,6 @@ nv04_fifo_unload_context(struct drm_device *dev)
RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH)); RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE)); RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1)); RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
dev_priv->engine.instmem.finish_access(dev);
nv04_fifo_do_load_context(dev, pfifo->channels - 1); nv04_fifo_do_load_context(dev, pfifo->channels - 1);
nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
...@@ -297,6 +292,7 @@ nv04_fifo_init(struct drm_device *dev) ...@@ -297,6 +292,7 @@ nv04_fifo_init(struct drm_device *dev)
nv04_fifo_init_intr(dev); nv04_fifo_init_intr(dev);
pfifo->enable(dev); pfifo->enable(dev);
pfifo->reassign(dev, true);
for (i = 0; i < dev_priv->engine.fifo.channels; i++) { for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
if (dev_priv->fifos[i]) { if (dev_priv->fifos[i]) {
......
...@@ -342,7 +342,7 @@ static uint32_t nv04_graph_ctx_regs[] = { ...@@ -342,7 +342,7 @@ static uint32_t nv04_graph_ctx_regs[] = {
}; };
struct graph_state { struct graph_state {
int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)]; uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
}; };
struct nouveau_channel * struct nouveau_channel *
...@@ -527,8 +527,7 @@ static int ...@@ -527,8 +527,7 @@ static int
nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
int mthd, uint32_t data) int mthd, uint32_t data)
{ {
chan->fence.last_sequence_irq = data; atomic_set(&chan->fence.last_sequence_irq, data);
nouveau_fence_handler(chan->dev, chan->id);
return 0; return 0;
} }
......
...@@ -49,10 +49,8 @@ nv04_instmem_determine_amount(struct drm_device *dev) ...@@ -49,10 +49,8 @@ nv04_instmem_determine_amount(struct drm_device *dev)
NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10); NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10);
/* Clear all of it, except the BIOS image that's in the first 64KiB */ /* Clear all of it, except the BIOS image that's in the first 64KiB */
dev_priv->engine.instmem.prepare_access(dev, true);
for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4) for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4)
nv_wi32(dev, i, 0x00000000); nv_wi32(dev, i, 0x00000000);
dev_priv->engine.instmem.finish_access(dev);
} }
static void static void
...@@ -106,7 +104,7 @@ int nv04_instmem_init(struct drm_device *dev) ...@@ -106,7 +104,7 @@ int nv04_instmem_init(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t offset; uint32_t offset;
int ret = 0; int ret;
nv04_instmem_determine_amount(dev); nv04_instmem_determine_amount(dev);
nv04_instmem_configure_fixed_tables(dev); nv04_instmem_configure_fixed_tables(dev);
...@@ -129,14 +127,14 @@ int nv04_instmem_init(struct drm_device *dev) ...@@ -129,14 +127,14 @@ int nv04_instmem_init(struct drm_device *dev)
offset = 0x40000; offset = 0x40000;
} }
ret = nouveau_mem_init_heap(&dev_priv->ramin_heap, ret = drm_mm_init(&dev_priv->ramin_heap, offset,
offset, dev_priv->ramin_rsvd_vram - offset); dev_priv->ramin_rsvd_vram - offset);
if (ret) { if (ret) {
dev_priv->ramin_heap = NULL; NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret);
NV_ERROR(dev, "Failed to init RAMIN heap\n"); return ret;
} }
return ret; return 0;
} }
void void
...@@ -186,12 +184,7 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) ...@@ -186,12 +184,7 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
} }
void void
nv04_instmem_prepare_access(struct drm_device *dev, bool write) nv04_instmem_flush(struct drm_device *dev)
{
}
void
nv04_instmem_finish_access(struct drm_device *dev)
{ {
} }
......
...@@ -11,6 +11,10 @@ nv04_mc_init(struct drm_device *dev) ...@@ -11,6 +11,10 @@ nv04_mc_init(struct drm_device *dev)
*/ */
nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
/* Disable PROM access. */
nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
return 0; return 0;
} }
......
...@@ -34,69 +34,26 @@ ...@@ -34,69 +34,26 @@
#include "i2c/ch7006.h" #include "i2c/ch7006.h"
static struct { static struct i2c_board_info nv04_tv_encoder_info[] = {
struct i2c_board_info board_info;
struct drm_encoder_funcs funcs;
struct drm_encoder_helper_funcs hfuncs;
void *params;
} nv04_tv_encoder_info[] = {
{ {
.board_info = { I2C_BOARD_INFO("ch7006", 0x75) }, I2C_BOARD_INFO("ch7006", 0x75),
.params = &(struct ch7006_encoder_params) { .platform_data = &(struct ch7006_encoder_params) {
CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER, CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
0, 0, 0, 0, 0, 0,
CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED, CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
}
}, },
}, { }
}; };
static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr)
{
struct i2c_msg msg = {
.addr = addr,
.len = 0,
};
return i2c_transfer(adapter, &msg, 1) == 1;
}
int nv04_tv_identify(struct drm_device *dev, int i2c_index) int nv04_tv_identify(struct drm_device *dev, int i2c_index)
{ {
struct nouveau_i2c_chan *i2c; return nouveau_i2c_identify(dev, "TV encoder",
bool was_locked; nv04_tv_encoder_info, i2c_index);
int i, ret;
NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index);
i2c = nouveau_i2c_find(dev, i2c_index);
if (!i2c)
return -ENODEV;
was_locked = NVLockVgaCrtcs(dev, false);
for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) {
if (probe_i2c_addr(&i2c->adapter,
nv04_tv_encoder_info[i].board_info.addr)) {
ret = i;
break;
}
}
if (i < ARRAY_SIZE(nv04_tv_encoder_info)) {
NV_TRACE(dev, "Detected TV encoder: %s\n",
nv04_tv_encoder_info[i].board_info.type);
} else {
NV_TRACE(dev, "No TV encoders found.\n");
i = -ENODEV;
}
NVLockVgaCrtcs(dev, was_locked);
return i;
} }
#define PLLSEL_TV_CRTC1_MASK \ #define PLLSEL_TV_CRTC1_MASK \
(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \ (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \
| NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1) | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
...@@ -214,30 +171,32 @@ static void nv04_tv_commit(struct drm_encoder *encoder) ...@@ -214,30 +171,32 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
static void nv04_tv_destroy(struct drm_encoder *encoder) static void nv04_tv_destroy(struct drm_encoder *encoder)
{ {
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
to_encoder_slave(encoder)->slave_funcs->destroy(encoder); to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(nv_encoder); kfree(encoder->helper_private);
kfree(nouveau_encoder(encoder));
} }
int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) static const struct drm_encoder_funcs nv04_tv_funcs = {
.destroy = nv04_tv_destroy,
};
int
nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
{ {
struct nouveau_encoder *nv_encoder; struct nouveau_encoder *nv_encoder;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_device *dev = connector->dev;
struct i2c_adapter *adap; struct drm_encoder_helper_funcs *hfuncs;
struct drm_encoder_funcs *funcs = NULL; struct drm_encoder_slave_funcs *sfuncs;
struct drm_encoder_helper_funcs *hfuncs = NULL; struct nouveau_i2c_chan *i2c =
struct drm_encoder_slave_funcs *sfuncs = NULL; nouveau_i2c_find(dev, entry->i2c_index);
int i2c_index = entry->i2c_index;
int type, ret; int type, ret;
bool was_locked;
/* Ensure that we can talk to this encoder */ /* Ensure that we can talk to this encoder */
type = nv04_tv_identify(dev, i2c_index); type = nv04_tv_identify(dev, entry->i2c_index);
if (type < 0) if (type < 0)
return type; return type;
...@@ -246,41 +205,32 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) ...@@ -246,41 +205,32 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
if (!nv_encoder) if (!nv_encoder)
return -ENOMEM; return -ENOMEM;
hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
if (!hfuncs) {
ret = -ENOMEM;
goto fail_free;
}
/* Initialize the common members */ /* Initialize the common members */
encoder = to_drm_encoder(nv_encoder); encoder = to_drm_encoder(nv_encoder);
funcs = &nv04_tv_encoder_info[type].funcs; drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
hfuncs = &nv04_tv_encoder_info[type].hfuncs;
drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC);
drm_encoder_helper_add(encoder, hfuncs); drm_encoder_helper_add(encoder, hfuncs);
encoder->possible_crtcs = entry->heads; encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0; encoder->possible_clones = 0;
nv_encoder->dcb = entry; nv_encoder->dcb = entry;
nv_encoder->or = ffs(entry->or) - 1; nv_encoder->or = ffs(entry->or) - 1;
/* Run the slave-specific initialization */ /* Run the slave-specific initialization */
adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter; ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
&i2c->adapter, &nv04_tv_encoder_info[type]);
was_locked = NVLockVgaCrtcs(dev, false);
ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
&nv04_tv_encoder_info[type].board_info);
NVLockVgaCrtcs(dev, was_locked);
if (ret < 0) if (ret < 0)
goto fail; goto fail_cleanup;
/* Fill the function pointers */ /* Fill the function pointers */
sfuncs = to_encoder_slave(encoder)->slave_funcs; sfuncs = to_encoder_slave(encoder)->slave_funcs;
*funcs = (struct drm_encoder_funcs) {
.destroy = nv04_tv_destroy,
};
*hfuncs = (struct drm_encoder_helper_funcs) { *hfuncs = (struct drm_encoder_helper_funcs) {
.dpms = nv04_tv_dpms, .dpms = nv04_tv_dpms,
.save = sfuncs->save, .save = sfuncs->save,
...@@ -292,14 +242,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry) ...@@ -292,14 +242,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
.detect = sfuncs->detect, .detect = sfuncs->detect,
}; };
/* Set the slave encoder configuration */ /* Attach it to the specified connector. */
sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params); sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data);
sfuncs->create_resources(encoder, connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0; return 0;
fail: fail_cleanup:
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(hfuncs);
fail_free:
kfree(nv_encoder); kfree(nv_encoder);
return ret; return ret;
} }
...@@ -55,7 +55,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan) ...@@ -55,7 +55,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
/* Fill entries that are seen filled in dumps of nvidia driver just /* Fill entries that are seen filled in dumps of nvidia driver just
* after channel's is put into DMA mode * after channel's is put into DMA mode
*/ */
dev_priv->engine.instmem.prepare_access(dev, true);
nv_wi32(dev, fc + 0, chan->pushbuf_base); nv_wi32(dev, fc + 0, chan->pushbuf_base);
nv_wi32(dev, fc + 4, chan->pushbuf_base); nv_wi32(dev, fc + 4, chan->pushbuf_base);
nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4); nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4);
...@@ -66,7 +65,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan) ...@@ -66,7 +65,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
NV_PFIFO_CACHE1_BIG_ENDIAN | NV_PFIFO_CACHE1_BIG_ENDIAN |
#endif #endif
0); 0);
dev_priv->engine.instmem.finish_access(dev);
/* enable the fifo dma operation */ /* enable the fifo dma operation */
nv_wr32(dev, NV04_PFIFO_MODE, nv_wr32(dev, NV04_PFIFO_MODE,
...@@ -91,8 +89,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid) ...@@ -91,8 +89,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid)
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
uint32_t fc = NV10_RAMFC(chid), tmp; uint32_t fc = NV10_RAMFC(chid), tmp;
dev_priv->engine.instmem.prepare_access(dev, false);
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0)); nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4)); nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8)); nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
...@@ -117,8 +113,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid) ...@@ -117,8 +113,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid)
nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48)); nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48));
out: out:
dev_priv->engine.instmem.finish_access(dev);
nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
} }
...@@ -155,8 +149,6 @@ nv10_fifo_unload_context(struct drm_device *dev) ...@@ -155,8 +149,6 @@ nv10_fifo_unload_context(struct drm_device *dev)
return 0; return 0;
fc = NV10_RAMFC(chid); fc = NV10_RAMFC(chid);
dev_priv->engine.instmem.prepare_access(dev, true);
nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); nv_wi32(dev, fc + 0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); nv_wi32(dev, fc + 4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT)); nv_wi32(dev, fc + 8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
...@@ -179,8 +171,6 @@ nv10_fifo_unload_context(struct drm_device *dev) ...@@ -179,8 +171,6 @@ nv10_fifo_unload_context(struct drm_device *dev)
nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET)); nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
out: out:
dev_priv->engine.instmem.finish_access(dev);
nv10_fifo_do_load_context(dev, pfifo->channels - 1); nv10_fifo_do_load_context(dev, pfifo->channels - 1);
nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
return 0; return 0;
......
...@@ -55,7 +55,7 @@ get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift, ...@@ -55,7 +55,7 @@ get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
} }
int int
nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
{ {
struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
uint32_t reg, shift, mask, value; uint32_t reg, shift, mask, value;
...@@ -72,7 +72,7 @@ nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) ...@@ -72,7 +72,7 @@ nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
} }
int int
nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
{ {
struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
uint32_t reg, shift, mask, value; uint32_t reg, shift, mask, value;
......
...@@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ...@@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
uint32_t testval, regoffset = nv04_dac_output_offset(encoder); uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
...@@ -52,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ...@@ -52,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
head = (dacclk & 0x100) >> 8; head = (dacclk & 0x100) >> 8;
/* Save the previous state. */ /* Save the previous state. */
gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
...@@ -64,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ...@@ -64,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
/* Prepare the DAC for load detection. */ /* Prepare the DAC for load detection. */
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true); gpio->set(dev, DCB_GPIO_TVDAC1, true);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true); gpio->set(dev, DCB_GPIO_TVDAC0, true);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
...@@ -110,12 +111,27 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ...@@ -110,12 +111,27 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1); gpio->set(dev, DCB_GPIO_TVDAC1, gpio1);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0); gpio->set(dev, DCB_GPIO_TVDAC0, gpio0);
return sample; return sample;
} }
static bool
get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
{
/* Zotac FX5200 */
if (dev->pdev->device == 0x0322 &&
dev->pdev->subsystem_vendor == 0x19da &&
(dev->pdev->subsystem_device == 0x1035 ||
dev->pdev->subsystem_device == 0x2035)) {
*pin_mask = 0xc;
return false;
}
return true;
}
static enum drm_connector_status static enum drm_connector_status
nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{ {
...@@ -124,12 +140,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -124,12 +140,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
struct drm_mode_config *conf = &dev->mode_config; struct drm_mode_config *conf = &dev->mode_config;
struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
struct dcb_entry *dcb = tv_enc->base.dcb; struct dcb_entry *dcb = tv_enc->base.dcb;
bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask);
if (nv04_dac_in_use(encoder))
return connector_status_disconnected;
if (reliable) {
if (dev_priv->chipset == 0x42 || if (dev_priv->chipset == 0x42 ||
dev_priv->chipset == 0x43) dev_priv->chipset == 0x43)
tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; tv_enc->pin_mask =
nv42_tv_sample_load(encoder) >> 28 & 0xe;
else else
tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; tv_enc->pin_mask =
nv17_dac_sample_load(encoder) >> 28 & 0xe;
}
switch (tv_enc->pin_mask) { switch (tv_enc->pin_mask) {
case 0x2: case 0x2:
...@@ -154,7 +178,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) ...@@ -154,7 +178,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
conf->tv_subconnector_property, conf->tv_subconnector_property,
tv_enc->subconnector); tv_enc->subconnector);
if (tv_enc->subconnector) { if (!reliable) {
return connector_status_unknown;
} else if (tv_enc->subconnector) {
NV_INFO(dev, "Load detected on output %c\n", NV_INFO(dev, "Load detected on output %c\n",
'@' + ffs(dcb->or)); '@' + ffs(dcb->or));
return connector_status_connected; return connector_status_connected;
...@@ -296,6 +322,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, ...@@ -296,6 +322,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
{ {
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
if (nv04_dac_in_use(encoder))
return false;
if (tv_norm->kind == CTV_ENC_MODE) if (tv_norm->kind == CTV_ENC_MODE)
adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock; adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
else else
...@@ -307,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, ...@@ -307,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
...@@ -331,8 +362,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) ...@@ -331,8 +362,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)
nv_load_ptv(dev, regs, 200); nv_load_ptv(dev, regs, 200);
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
} }
...@@ -744,8 +775,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = { ...@@ -744,8 +775,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
.destroy = nv17_tv_destroy, .destroy = nv17_tv_destroy,
}; };
int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) int
nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
{ {
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct nv17_tv_encoder *tv_enc = NULL; struct nv17_tv_encoder *tv_enc = NULL;
...@@ -774,5 +807,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry) ...@@ -774,5 +807,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
encoder->possible_crtcs = entry->heads; encoder->possible_crtcs = entry->heads;
encoder->possible_clones = 0; encoder->possible_clones = 0;
nv17_tv_create_resources(encoder, connector);
drm_mode_connector_attach_encoder(connector, encoder);
return 0; return 0;
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment