summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_acpi.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hdmi.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.c199
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_i2c.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_pm.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv10_gpio.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_sor.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fb.c5
9 files changed, 41 insertions, 185 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 7814a760c164..284bd25d5d21 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -270,7 +270,7 @@ static bool nouveau_dsm_detect(void)
struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
struct pci_dev *pdev = NULL;
int has_dsm = 0;
- int has_optimus;
+ int has_optimus = 0;
int vga_count = 0;
bool guid_valid;
int retval;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 80963d05b54a..0be4a815e706 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -6156,10 +6156,14 @@ dcb_fake_connectors(struct nvbios *bios)
/* heuristic: if we ever get a non-zero connector field, assume
* that all the indices are valid and we don't need fake them.
+ *
+ * and, as usual, a blacklist of boards with bad bios data..
*/
- for (i = 0; i < dcbt->entries; i++) {
- if (dcbt->entry[i].connector)
- return;
+ if (!nv_match_device(bios->dev, 0x0392, 0x107d, 0x20a2)) {
+ for (i = 0; i < dcbt->entries; i++) {
+ if (dcbt->entry[i].connector)
+ return;
+ }
}
/* no useful connector info available, we need to make it up
diff --git a/drivers/gpu/drm/nouveau/nouveau_hdmi.c b/drivers/gpu/drm/nouveau/nouveau_hdmi.c
index 59ea1c14eca0..c3de36384522 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c
@@ -32,7 +32,9 @@ static bool
hdmi_sor(struct drm_encoder *encoder)
{
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
- if (dev_priv->chipset < 0xa3)
+ if (dev_priv->chipset < 0xa3 ||
+ dev_priv->chipset == 0xaa ||
+ dev_priv->chipset == 0xac)
return false;
return true;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
index e2be95af2e52..77e564667b5c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -29,10 +29,6 @@
#include "nouveau_i2c.h"
#include "nouveau_hw.h"
-#define T_TIMEOUT 2200000
-#define T_RISEFALL 1000
-#define T_HOLD 5000
-
static void
i2c_drive_scl(void *data, int state)
{
@@ -113,175 +109,6 @@ i2c_sense_sda(void *data)
return 0;
}
-static void
-i2c_delay(struct nouveau_i2c_chan *port, u32 nsec)
-{
- udelay((nsec + 500) / 1000);
-}
-
-static bool
-i2c_raise_scl(struct nouveau_i2c_chan *port)
-{
- u32 timeout = T_TIMEOUT / T_RISEFALL;
-
- i2c_drive_scl(port, 1);
- do {
- i2c_delay(port, T_RISEFALL);
- } while (!i2c_sense_scl(port) && --timeout);
-
- return timeout != 0;
-}
-
-static int
-i2c_start(struct nouveau_i2c_chan *port)
-{
- int ret = 0;
-
- port->state = i2c_sense_scl(port);
- port->state |= i2c_sense_sda(port) << 1;
- if (port->state != 3) {
- i2c_drive_scl(port, 0);
- i2c_drive_sda(port, 1);
- if (!i2c_raise_scl(port))
- ret = -EBUSY;
- }
-
- i2c_drive_sda(port, 0);
- i2c_delay(port, T_HOLD);
- i2c_drive_scl(port, 0);
- i2c_delay(port, T_HOLD);
- return ret;
-}
-
-static void
-i2c_stop(struct nouveau_i2c_chan *port)
-{
- i2c_drive_scl(port, 0);
- i2c_drive_sda(port, 0);
- i2c_delay(port, T_RISEFALL);
-
- i2c_drive_scl(port, 1);
- i2c_delay(port, T_HOLD);
- i2c_drive_sda(port, 1);
- i2c_delay(port, T_HOLD);
-}
-
-static int
-i2c_bitw(struct nouveau_i2c_chan *port, int sda)
-{
- i2c_drive_sda(port, sda);
- i2c_delay(port, T_RISEFALL);
-
- if (!i2c_raise_scl(port))
- return -ETIMEDOUT;
- i2c_delay(port, T_HOLD);
-
- i2c_drive_scl(port, 0);
- i2c_delay(port, T_HOLD);
- return 0;
-}
-
-static int
-i2c_bitr(struct nouveau_i2c_chan *port)
-{
- int sda;
-
- i2c_drive_sda(port, 1);
- i2c_delay(port, T_RISEFALL);
-
- if (!i2c_raise_scl(port))
- return -ETIMEDOUT;
- i2c_delay(port, T_HOLD);
-
- sda = i2c_sense_sda(port);
-
- i2c_drive_scl(port, 0);
- i2c_delay(port, T_HOLD);
- return sda;
-}
-
-static int
-i2c_get_byte(struct nouveau_i2c_chan *port, u8 *byte, bool last)
-{
- int i, bit;
-
- *byte = 0;
- for (i = 7; i >= 0; i--) {
- bit = i2c_bitr(port);
- if (bit < 0)
- return bit;
- *byte |= bit << i;
- }
-
- return i2c_bitw(port, last ? 1 : 0);
-}
-
-static int
-i2c_put_byte(struct nouveau_i2c_chan *port, u8 byte)
-{
- int i, ret;
- for (i = 7; i >= 0; i--) {
- ret = i2c_bitw(port, !!(byte & (1 << i)));
- if (ret < 0)
- return ret;
- }
-
- ret = i2c_bitr(port);
- if (ret == 1) /* nack */
- ret = -EIO;
- return ret;
-}
-
-static int
-i2c_addr(struct nouveau_i2c_chan *port, struct i2c_msg *msg)
-{
- u32 addr = msg->addr << 1;
- if (msg->flags & I2C_M_RD)
- addr |= 1;
- return i2c_put_byte(port, addr);
-}
-
-static int
-i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
- struct nouveau_i2c_chan *port = (struct nouveau_i2c_chan *)adap;
- struct i2c_msg *msg = msgs;
- int ret = 0, mcnt = num;
-
- while (!ret && mcnt--) {
- u8 remaining = msg->len;
- u8 *ptr = msg->buf;
-
- ret = i2c_start(port);
- if (ret == 0)
- ret = i2c_addr(port, msg);
-
- if (msg->flags & I2C_M_RD) {
- while (!ret && remaining--)
- ret = i2c_get_byte(port, ptr++, !remaining);
- } else {
- while (!ret && remaining--)
- ret = i2c_put_byte(port, *ptr++);
- }
-
- msg++;
- }
-
- i2c_stop(port);
- return (ret < 0) ? ret : num;
-}
-
-static u32
-i2c_bit_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-const struct i2c_algorithm nouveau_i2c_bit_algo = {
- .master_xfer = i2c_bit_xfer,
- .functionality = i2c_bit_func
-};
-
static const uint32_t nv50_i2c_port[] = {
0x00e138, 0x00e150, 0x00e168, 0x00e180,
0x00e254, 0x00e274, 0x00e764, 0x00e780,
@@ -384,12 +211,10 @@ nouveau_i2c_init(struct drm_device *dev)
case 0: /* NV04:NV50 */
port->drive = entry[0];
port->sense = entry[1];
- port->adapter.algo = &nouveau_i2c_bit_algo;
break;
case 4: /* NV4E */
port->drive = 0x600800 + entry[1];
port->sense = port->drive;
- port->adapter.algo = &nouveau_i2c_bit_algo;
break;
case 5: /* NV50- */
port->drive = entry[0] & 0x0f;
@@ -402,7 +227,6 @@ nouveau_i2c_init(struct drm_device *dev)
port->drive = 0x00d014 + (port->drive * 0x20);
port->sense = port->drive;
}
- port->adapter.algo = &nouveau_i2c_bit_algo;
break;
case 6: /* NV50- DP AUX */
port->drive = entry[0];
@@ -413,7 +237,7 @@ nouveau_i2c_init(struct drm_device *dev)
break;
}
- if (!port->adapter.algo) {
+ if (!port->adapter.algo && !port->drive) {
NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
i, port->type, port->drive, port->sense);
kfree(port);
@@ -429,7 +253,26 @@ nouveau_i2c_init(struct drm_device *dev)
port->dcb = ROM32(entry[0]);
i2c_set_adapdata(&port->adapter, i2c);
- ret = i2c_add_adapter(&port->adapter);
+ if (port->adapter.algo != &nouveau_dp_i2c_algo) {
+ port->adapter.algo_data = &port->bit;
+ port->bit.udelay = 10;
+ port->bit.timeout = usecs_to_jiffies(2200);
+ port->bit.data = port;
+ port->bit.setsda = i2c_drive_sda;
+ port->bit.setscl = i2c_drive_scl;
+ port->bit.getsda = i2c_sense_sda;
+ port->bit.getscl = i2c_sense_scl;
+
+ i2c_drive_scl(port, 0);
+ i2c_drive_sda(port, 1);
+ i2c_drive_scl(port, 1);
+
+ ret = i2c_bit_add_bus(&port->adapter);
+ } else {
+ port->adapter.algo = &nouveau_dp_i2c_algo;
+ ret = i2c_add_adapter(&port->adapter);
+ }
+
if (ret) {
NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret);
kfree(port);
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h
index 4d2e4e9031be..1d083893a4d7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.h
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h
@@ -34,6 +34,7 @@
struct nouveau_i2c_chan {
struct i2c_adapter adapter;
struct drm_device *dev;
+ struct i2c_algo_bit_data bit;
struct list_head head;
u8 index;
u8 type;
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 34d591b7d4ef..da3e7c3abab7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -235,6 +235,7 @@ nouveau_pm_profile_set(struct drm_device *dev, const char *profile)
return -EPERM;
strncpy(string, profile, sizeof(string));
+ string[sizeof(string) - 1] = 0;
if ((ptr = strchr(string, '\n')))
*ptr = '\0';
diff --git a/drivers/gpu/drm/nouveau/nv10_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c
index 550ad3fcf0af..9d79180069df 100644
--- a/drivers/gpu/drm/nouveau/nv10_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv10_gpio.c
@@ -65,7 +65,7 @@ nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out)
if (line < 10) {
line = (line - 2) * 4;
reg = NV_PCRTC_GPIO_EXT;
- mask = 0x00000003 << ((line - 2) * 4);
+ mask = 0x00000003;
data = (dir << 1) | out;
} else
if (line < 14) {
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index a7844ab6a50c..274640212475 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -42,7 +42,7 @@ nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane)
struct drm_nouveau_private *dev_priv = dev->dev_private;
static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */
static const u8 nv50[] = { 16, 8, 0, 24 };
- if (dev_priv->card_type == 0xaf)
+ if (dev_priv->chipset == 0xaf)
return nvaf[lane];
return nv50[lane];
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index 5bf55038fd92..f704e942372e 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -54,6 +54,11 @@ nvc0_mfb_isr(struct drm_device *dev)
nvc0_mfb_subp_isr(dev, unit, subp);
units &= ~(1 << unit);
}
+
+ /* we do something horribly wrong and upset PMFB a lot, so mask off
+ * interrupts from it after the first one until it's fixed
+ */
+ nv_mask(dev, 0x000640, 0x02000000, 0x00000000);
}
static void
OpenPOWER on IntegriCloud