提交 2e6713c7 编写于 作者: R Rafael J. Wysocki

Merge branch 'master' into for-linus

...@@ -2006,6 +2006,9 @@ E: paul@laufernet.com ...@@ -2006,6 +2006,9 @@ E: paul@laufernet.com
D: Soundblaster driver fixes, ISAPnP quirk D: Soundblaster driver fixes, ISAPnP quirk
S: California, USA S: California, USA
N: Jonathan Layes
D: ARPD support
N: Tom Lees N: Tom Lees
E: tom@lpsg.demon.co.uk E: tom@lpsg.demon.co.uk
W: http://www.lpsg.demon.co.uk/ W: http://www.lpsg.demon.co.uk/
...@@ -3802,6 +3805,9 @@ S: van Bronckhorststraat 12 ...@@ -3802,6 +3805,9 @@ S: van Bronckhorststraat 12
S: 2612 XV Delft S: 2612 XV Delft
S: The Netherlands S: The Netherlands
N: Thomas Woller
D: CS461x Cirrus Logic sound driver
N: David Woodhouse N: David Woodhouse
E: dwmw2@infradead.org E: dwmw2@infradead.org
D: JFFS2 file system, Memory Technology Device subsystem, D: JFFS2 file system, Memory Technology Device subsystem,
......
...@@ -23,7 +23,8 @@ interface. ...@@ -23,7 +23,8 @@ interface.
Using sysfs Using sysfs
~~~~~~~~~~~ ~~~~~~~~~~~
sysfs is always compiled in. You can access it by doing: sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
it by doing:
mount -t sysfs sysfs /sys mount -t sysfs sysfs /sys
......
...@@ -66,7 +66,8 @@ On all - write a character to /proc/sysrq-trigger. e.g.: ...@@ -66,7 +66,8 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
'b' - Will immediately reboot the system without syncing or unmounting 'b' - Will immediately reboot the system without syncing or unmounting
your disks. your disks.
'c' - Will perform a kexec reboot in order to take a crashdump. 'c' - Will perform a system crash by a NULL pointer dereference.
A crashdump will be taken if configured.
'd' - Shows all locks that are held. 'd' - Shows all locks that are held.
...@@ -141,8 +142,8 @@ useful when you want to exit a program that will not let you switch consoles. ...@@ -141,8 +142,8 @@ useful when you want to exit a program that will not let you switch consoles.
re'B'oot is good when you're unable to shut down. But you should also 'S'ync re'B'oot is good when you're unable to shut down. But you should also 'S'ync
and 'U'mount first. and 'U'mount first.
'C'rashdump can be used to manually trigger a crashdump when the system is hung. 'C'rash can be used to manually trigger a crashdump when the system is hung.
The kernel needs to have been built with CONFIG_KEXEC enabled. Note that this just triggers a crash if there is no dump mechanism available.
'S'ync is great when your system is locked up, it allows you to sync your 'S'ync is great when your system is locked up, it allows you to sync your
disks and will certainly lessen the chance of data loss and fscking. Note disks and will certainly lessen the chance of data loss and fscking. Note
......
此差异已折叠。
...@@ -103,6 +103,7 @@ EXPORT_SYMBOL(kmap); ...@@ -103,6 +103,7 @@ EXPORT_SYMBOL(kmap);
EXPORT_SYMBOL(kunmap); EXPORT_SYMBOL(kunmap);
EXPORT_SYMBOL(kmap_atomic); EXPORT_SYMBOL(kmap_atomic);
EXPORT_SYMBOL(kunmap_atomic); EXPORT_SYMBOL(kunmap_atomic);
EXPORT_SYMBOL(kmap_atomic_prot);
void __init set_highmem_pages_init(void) void __init set_highmem_pages_init(void)
{ {
......
...@@ -397,6 +397,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { ...@@ -397,6 +397,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
}, },
}, },
{ {
.callback = init_set_sci_en_on_resume,
.ident = "Hewlett-Packard HP G7000 Notebook PC",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"),
},
},
{
.callback = init_old_suspend_ordering, .callback = init_old_suspend_ordering,
.ident = "Panasonic CF51-2L", .ident = "Panasonic CF51-2L",
.matches = { .matches = {
......
...@@ -515,10 +515,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { ...@@ -515,10 +515,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
/* JMicron 360/1/3/5/6, match class to avoid IDE function */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
......
...@@ -596,9 +596,12 @@ static const struct ich_laptop ich_laptop[] = { ...@@ -596,9 +596,12 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
{ 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */ { 0x27DF, 0x1025, 0x0102 }, /* ICH7 on Acer 5602aWLMi */
{ 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
{ 0x27DF, 0x1028, 0x02b0 }, /* ICH7 on unknown Dell */
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x27DF, 0x103C, 0x361a }, /* ICH7 on unkown HP */
{ 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */ { 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
{ 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */
{ 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */
{ 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */
......
...@@ -1515,6 +1515,7 @@ static int ata_hpa_resize(struct ata_device *dev) ...@@ -1515,6 +1515,7 @@ static int ata_hpa_resize(struct ata_device *dev)
return rc; return rc;
} }
dev->n_native_sectors = native_sectors;
/* nothing to do? */ /* nothing to do? */
if (native_sectors <= sectors || !ata_ignore_hpa) { if (native_sectors <= sectors || !ata_ignore_hpa) {
...@@ -4099,6 +4100,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, ...@@ -4099,6 +4100,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
unsigned int readid_flags) unsigned int readid_flags)
{ {
u64 n_sectors = dev->n_sectors; u64 n_sectors = dev->n_sectors;
u64 n_native_sectors = dev->n_native_sectors;
int rc; int rc;
if (!ata_dev_enabled(dev)) if (!ata_dev_enabled(dev))
...@@ -4128,16 +4130,30 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, ...@@ -4128,16 +4130,30 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
/* verify n_sectors hasn't changed */ /* verify n_sectors hasn't changed */
if (dev->class == ATA_DEV_ATA && n_sectors && if (dev->class == ATA_DEV_ATA && n_sectors &&
dev->n_sectors != n_sectors) { dev->n_sectors != n_sectors) {
ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch " ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
"%llu != %llu\n", "%llu != %llu\n",
(unsigned long long)n_sectors, (unsigned long long)n_sectors,
(unsigned long long)dev->n_sectors); (unsigned long long)dev->n_sectors);
/*
/* restore original n_sectors */ * Something could have caused HPA to be unlocked
dev->n_sectors = n_sectors; * involuntarily. If n_native_sectors hasn't changed
* and the new size matches it, keep the device.
rc = -ENODEV; */
goto fail; if (dev->n_native_sectors == n_native_sectors &&
dev->n_sectors > n_sectors &&
dev->n_sectors == n_native_sectors) {
ata_dev_printk(dev, KERN_WARNING,
"new n_sectors matches native, probably "
"late HPA unlock, continuing\n");
/* keep using the old n_sectors */
dev->n_sectors = n_sectors;
} else {
/* restore original n_[native]_sectors and fail */
dev->n_native_sectors = n_native_sectors;
dev->n_sectors = n_sectors;
rc = -ENODEV;
goto fail;
}
} }
return 0; return 0;
......
...@@ -2327,7 +2327,7 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -2327,7 +2327,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
struct ata_port *ap = link->ap; struct ata_port *ap = link->ap;
struct ata_link *slave = ap->slave_link; struct ata_link *slave = ap->slave_link;
struct ata_eh_context *ehc = &link->eh_context; struct ata_eh_context *ehc = &link->eh_context;
struct ata_eh_context *sehc = &slave->eh_context; struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL;
unsigned int *classes = ehc->classes; unsigned int *classes = ehc->classes;
unsigned int lflags = link->flags; unsigned int lflags = link->flags;
int verbose = !(ehc->i.flags & ATA_EHI_QUIET); int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
......
...@@ -26,9 +26,7 @@ ...@@ -26,9 +26,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/ata_platform.h> #include <linux/ata_platform.h>
#include <mach/at91sam9260_matrix.h>
#include <mach/at91sam9_smc.h> #include <mach/at91sam9_smc.h>
#include <mach/at91sam9260.h>
#include <mach/board.h> #include <mach/board.h>
#include <mach/gpio.h> #include <mach/gpio.h>
...@@ -44,65 +42,62 @@ struct at91_ide_info { ...@@ -44,65 +42,62 @@ struct at91_ide_info {
unsigned long mode; unsigned long mode;
unsigned int cs; unsigned int cs;
struct clk *mck;
void __iomem *ide_addr; void __iomem *ide_addr;
void __iomem *alt_addr; void __iomem *alt_addr;
}; };
const struct ata_timing initial_timing = static const struct ata_timing initial_timing =
{XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0}; {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz) static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
{ {
unsigned long mul; unsigned long mul;
/* /*
* cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] = * cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] =
* x * (f / 1_000_000_000) = * x * (f / 1_000_000_000) =
* x * ((f * 65536) / 1_000_000_000) / 65536 = * x * ((f * 65536) / 1_000_000_000) / 65536 =
* x * (((f / 10_000) * 65536) / 100_000) / 65536 = * x * (((f / 10_000) * 65536) / 100_000) / 65536 =
*/ */
mul = (mck_hz / 10000) << 16; mul = (mck_hz / 10000) << 16;
mul /= 100000; mul /= 100000;
return (ns * mul + 65536) >> 16; /* rounding */ return (ns * mul + 65536) >> 16; /* rounding */
} }
static void set_smc_mode(struct at91_ide_info *info) static void set_smc_mode(struct at91_ide_info *info)
{ {
at91_sys_write(AT91_SMC_MODE(info->cs), info->mode); at91_sys_write(AT91_SMC_MODE(info->cs), info->mode);
return; return;
} }
static void set_smc_timing(struct device *dev, static void set_smc_timing(struct device *dev,
struct at91_ide_info *info, const struct ata_timing *ata) struct at91_ide_info *info, const struct ata_timing *ata)
{ {
int read_cycle, write_cycle, active, recover; unsigned long read_cycle, write_cycle, active, recover;
int nrd_setup, nrd_pulse, nrd_recover; unsigned long nrd_setup, nrd_pulse, nrd_recover;
int nwe_setup, nwe_pulse; unsigned long nwe_setup, nwe_pulse;
int ncs_write_setup, ncs_write_pulse; unsigned long ncs_write_setup, ncs_write_pulse;
int ncs_read_setup, ncs_read_pulse; unsigned long ncs_read_setup, ncs_read_pulse;
unsigned int mck_hz; unsigned long mck_hz;
struct clk *mck;
read_cycle = ata->cyc8b; read_cycle = ata->cyc8b;
nrd_setup = ata->setup; nrd_setup = ata->setup;
nrd_pulse = ata->act8b; nrd_pulse = ata->act8b;
nrd_recover = ata->rec8b; nrd_recover = ata->rec8b;
mck = clk_get(NULL, "mck"); mck_hz = clk_get_rate(info->mck);
BUG_ON(IS_ERR(mck));
mck_hz = clk_get_rate(mck);
read_cycle = calc_mck_cycles(read_cycle, mck_hz); read_cycle = calc_mck_cycles(read_cycle, mck_hz);
nrd_setup = calc_mck_cycles(nrd_setup, mck_hz); nrd_setup = calc_mck_cycles(nrd_setup, mck_hz);
nrd_pulse = calc_mck_cycles(nrd_pulse, mck_hz); nrd_pulse = calc_mck_cycles(nrd_pulse, mck_hz);
nrd_recover = calc_mck_cycles(nrd_recover, mck_hz); nrd_recover = calc_mck_cycles(nrd_recover, mck_hz);
clk_put(mck);
active = nrd_setup + nrd_pulse; active = nrd_setup + nrd_pulse;
recover = read_cycle - active; recover = read_cycle - active;
...@@ -121,13 +116,13 @@ static void set_smc_timing(struct device *dev, ...@@ -121,13 +116,13 @@ static void set_smc_timing(struct device *dev,
ncs_write_setup = ncs_read_setup; ncs_write_setup = ncs_read_setup;
ncs_write_pulse = ncs_read_pulse; ncs_write_pulse = ncs_read_pulse;
dev_dbg(dev, "ATA timings: nrd_setup = %d nrd_pulse = %d nrd_cycle = %d\n", dev_dbg(dev, "ATA timings: nrd_setup = %lu nrd_pulse = %lu nrd_cycle = %lu\n",
nrd_setup, nrd_pulse, read_cycle); nrd_setup, nrd_pulse, read_cycle);
dev_dbg(dev, "ATA timings: nwe_setup = %d nwe_pulse = %d nwe_cycle = %d\n", dev_dbg(dev, "ATA timings: nwe_setup = %lu nwe_pulse = %lu nwe_cycle = %lu\n",
nwe_setup, nwe_pulse, write_cycle); nwe_setup, nwe_pulse, write_cycle);
dev_dbg(dev, "ATA timings: ncs_read_setup = %d ncs_read_pulse = %d\n", dev_dbg(dev, "ATA timings: ncs_read_setup = %lu ncs_read_pulse = %lu\n",
ncs_read_setup, ncs_read_pulse); ncs_read_setup, ncs_read_pulse);
dev_dbg(dev, "ATA timings: ncs_write_setup = %d ncs_write_pulse = %d\n", dev_dbg(dev, "ATA timings: ncs_write_setup = %lu ncs_write_pulse = %lu\n",
ncs_write_setup, ncs_write_pulse); ncs_write_setup, ncs_write_pulse);
at91_sys_write(AT91_SMC_SETUP(info->cs), at91_sys_write(AT91_SMC_SETUP(info->cs),
...@@ -217,6 +212,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev) ...@@ -217,6 +212,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
struct resource *mem_res; struct resource *mem_res;
struct ata_host *host; struct ata_host *host;
struct ata_port *ap; struct ata_port *ap;
int irq_flags = 0; int irq_flags = 0;
int irq = 0; int irq = 0;
int ret; int ret;
...@@ -261,6 +257,13 @@ static int __devinit pata_at91_probe(struct platform_device *pdev) ...@@ -261,6 +257,13 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
} }
info->mck = clk_get(NULL, "mck");
if (IS_ERR(info->mck)) {
dev_err(dev, "failed to get access to mck clock\n");
return -ENODEV;
}
info->cs = board->chipselect; info->cs = board->chipselect;
info->mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | info->mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
AT91_SMC_EXNWMODE_READY | AT91_SMC_BAT_SELECT | AT91_SMC_EXNWMODE_READY | AT91_SMC_BAT_SELECT |
...@@ -304,6 +307,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev) ...@@ -304,6 +307,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
devm_iounmap(dev, info->ide_addr); devm_iounmap(dev, info->ide_addr);
err_ide_ioremap: err_ide_ioremap:
clk_put(info->mck);
kfree(info); kfree(info);
return ret; return ret;
...@@ -326,6 +330,7 @@ static int __devexit pata_at91_remove(struct platform_device *pdev) ...@@ -326,6 +330,7 @@ static int __devexit pata_at91_remove(struct platform_device *pdev)
devm_iounmap(dev, info->ide_addr); devm_iounmap(dev, info->ide_addr);
devm_iounmap(dev, info->alt_addr); devm_iounmap(dev, info->alt_addr);
clk_put(info->mck);
kfree(info); kfree(info);
return 0; return 0;
......
...@@ -653,7 +653,8 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance) ...@@ -653,7 +653,8 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance)
ap = host->ports[i]; ap = host->ports[i];
ocd = ap->dev->platform_data; ocd = ap->dev->platform_data;
if (!ap || (ap->flags & ATA_FLAG_DISABLED))
if (ap->flags & ATA_FLAG_DISABLED)
continue; continue;
ocd = ap->dev->platform_data; ocd = ap->dev->platform_data;
......
...@@ -411,6 +411,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { ...@@ -411,6 +411,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("CNF ", "CD-ROM", 0x46d7db81, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
......
...@@ -2514,7 +2514,7 @@ static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled) ...@@ -2514,7 +2514,7 @@ static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled)
char *when = "idle"; char *when = "idle";
ata_ehi_clear_desc(ehi); ata_ehi_clear_desc(ehi);
if (!ap || (ap->flags & ATA_FLAG_DISABLED)) { if (ap->flags & ATA_FLAG_DISABLED) {
when = "disabled"; when = "disabled";
} else if (edma_was_enabled) { } else if (edma_was_enabled) {
when = "EDMA enabled"; when = "EDMA enabled";
......
...@@ -532,7 +532,7 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance) ...@@ -532,7 +532,7 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance)
struct ata_port *ap = host->ports[i]; struct ata_port *ap = host->ports[i];
u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) if (unlikely(ap->flags & ATA_FLAG_DISABLED))
continue; continue;
/* turn off SATA_IRQ if not supported */ /* turn off SATA_IRQ if not supported */
......
...@@ -180,7 +180,6 @@ static ssize_t firmware_loading_store(struct device *dev, ...@@ -180,7 +180,6 @@ static ssize_t firmware_loading_store(struct device *dev,
goto err; goto err;
} }
/* Pages will be freed by vfree() */ /* Pages will be freed by vfree() */
fw_priv->pages = NULL;
fw_priv->page_array_size = 0; fw_priv->page_array_size = 0;
fw_priv->nr_pages = 0; fw_priv->nr_pages = 0;
complete(&fw_priv->completion); complete(&fw_priv->completion);
......
...@@ -275,9 +275,9 @@ int sysdev_register(struct sys_device *sysdev) ...@@ -275,9 +275,9 @@ int sysdev_register(struct sys_device *sysdev)
drv->add(sysdev); drv->add(sysdev);
} }
mutex_unlock(&sysdev_drivers_lock); mutex_unlock(&sysdev_drivers_lock);
kobject_uevent(&sysdev->kobj, KOBJ_ADD);
} }
kobject_uevent(&sysdev->kobj, KOBJ_ADD);
return error; return error;
} }
......
...@@ -1583,6 +1583,7 @@ static int n_tty_open(struct tty_struct *tty) ...@@ -1583,6 +1583,7 @@ static int n_tty_open(struct tty_struct *tty)
static inline int input_available_p(struct tty_struct *tty, int amt) static inline int input_available_p(struct tty_struct *tty, int amt)
{ {
tty_flush_to_ldisc(tty);
if (tty->icanon) { if (tty->icanon) {
if (tty->canon_data) if (tty->canon_data)
return 1; return 1;
......
...@@ -52,7 +52,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp) ...@@ -52,7 +52,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
return; return;
tty->link->packet = 0; tty->link->packet = 0;
set_bit(TTY_OTHER_CLOSED, &tty->link->flags); set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
tty_flip_buffer_push(tty->link);
wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait); wake_up_interruptible(&tty->link->write_wait);
if (tty->driver->subtype == PTY_TYPE_MASTER) { if (tty->driver->subtype == PTY_TYPE_MASTER) {
...@@ -208,7 +207,6 @@ static int pty_open(struct tty_struct *tty, struct file *filp) ...@@ -208,7 +207,6 @@ static int pty_open(struct tty_struct *tty, struct file *filp)
clear_bit(TTY_OTHER_CLOSED, &tty->link->flags); clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
set_bit(TTY_THROTTLED, &tty->flags); set_bit(TTY_THROTTLED, &tty->flags);
retval = 0; retval = 0;
tty->low_latency = 1;
out: out:
return retval; return retval;
} }
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/vt_kern.h> #include <linux/vt_kern.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/kexec.h>
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
#include <linux/oom.h> #include <linux/oom.h>
...@@ -124,9 +123,12 @@ static struct sysrq_key_op sysrq_unraw_op = { ...@@ -124,9 +123,12 @@ static struct sysrq_key_op sysrq_unraw_op = {
static void sysrq_handle_crash(int key, struct tty_struct *tty) static void sysrq_handle_crash(int key, struct tty_struct *tty)
{ {
char *killer = NULL; char *killer = NULL;
panic_on_oops = 1; /* force panic */
wmb();
*killer = 1; *killer = 1;
} }
static struct sysrq_key_op sysrq_crashdump_op = { static struct sysrq_key_op sysrq_crash_op = {
.handler = sysrq_handle_crash, .handler = sysrq_handle_crash,
.help_msg = "Crash", .help_msg = "Crash",
.action_msg = "Trigger a crash", .action_msg = "Trigger a crash",
...@@ -401,7 +403,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { ...@@ -401,7 +403,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
*/ */
NULL, /* a */ NULL, /* a */
&sysrq_reboot_op, /* b */ &sysrq_reboot_op, /* b */
&sysrq_crashdump_op, /* c & ibm_emac driver debug */ &sysrq_crash_op, /* c & ibm_emac driver debug */
&sysrq_showlocks_op, /* d */ &sysrq_showlocks_op, /* d */
&sysrq_term_op, /* e */ &sysrq_term_op, /* e */
&sysrq_moom_op, /* f */ &sysrq_moom_op, /* f */
......
...@@ -461,6 +461,19 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -461,6 +461,19 @@ static void flush_to_ldisc(struct work_struct *work)
tty_ldisc_deref(disc); tty_ldisc_deref(disc);
} }
/**
* tty_flush_to_ldisc
* @tty: tty to push
*
* Push the terminal flip buffers to the line discipline.
*
* Must not be called from IRQ context.
*/
void tty_flush_to_ldisc(struct tty_struct *tty)
{
flush_to_ldisc(&tty->buf.work.work);
}
/** /**
* tty_flip_buffer_push - terminal * tty_flip_buffer_push - terminal
* @tty: tty to push * @tty: tty to push
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
/* Intel X38 register addresses - device 0 function 0 - DRAM Controller */ /* Intel X38 register addresses - device 0 function 0 - DRAM Controller */
#define X38_MCHBAR_LOW 0x48 /* MCH Memory Mapped Register BAR */ #define X38_MCHBAR_LOW 0x48 /* MCH Memory Mapped Register BAR */
#define X38_MCHBAR_HIGH 0x4b #define X38_MCHBAR_HIGH 0x4c
#define X38_MCHBAR_MASK 0xfffffc000ULL /* bits 35:14 */ #define X38_MCHBAR_MASK 0xfffffc000ULL /* bits 35:14 */
#define X38_MMR_WINDOW_SIZE 16384 #define X38_MMR_WINDOW_SIZE 16384
......
...@@ -13,7 +13,8 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \ ...@@ -13,7 +13,8 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \
radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \ radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \
radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \ radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \
radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \
radeon_test.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
......
...@@ -31,6 +31,132 @@ ...@@ -31,6 +31,132 @@
#include "atom.h" #include "atom.h"
#include "atom-bits.h" #include "atom-bits.h"
static void atombios_overscan_setup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
SET_CRTC_OVERSCAN_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
int a1, a2;
memset(&args, 0, sizeof(args));
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
args.ucCRTC = radeon_crtc->crtc_id;
switch (radeon_crtc->rmx_type) {
case RMX_CENTER:
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
case RMX_ASPECT:
a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
if (a1 > a2) {
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
} else if (a2 > a1) {
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
case RMX_FULL:
default:
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
}
}
static void atombios_scaler_setup(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
/* fixme - fill in enc_priv for atom dac */
enum radeon_tv_std tv_std = TV_STD_NTSC;
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
return;
memset(&args, 0, sizeof(args));
args.ucScaler = radeon_crtc->crtc_id;
if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
switch (tv_std) {
case TV_STD_NTSC:
default:
args.ucTVStandard = ATOM_TV_NTSC;
break;
case TV_STD_PAL:
args.ucTVStandard = ATOM_TV_PAL;
break;
case TV_STD_PAL_M:
args.ucTVStandard = ATOM_TV_PALM;
break;
case TV_STD_PAL_60:
args.ucTVStandard = ATOM_TV_PAL60;
break;
case TV_STD_NTSC_J:
args.ucTVStandard = ATOM_TV_NTSCJ;
break;
case TV_STD_SCART_PAL:
args.ucTVStandard = ATOM_TV_PAL; /* ??? */
break;
case TV_STD_SECAM:
args.ucTVStandard = ATOM_TV_SECAM;
break;
case TV_STD_PAL_CN:
args.ucTVStandard = ATOM_TV_PALCN;
break;
}
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
args.ucTVStandard = ATOM_TV_CV;
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else {
switch (radeon_crtc->rmx_type) {
case RMX_FULL:
args.ucEnable = ATOM_SCALER_EXPANSION;
break;
case RMX_CENTER:
args.ucEnable = ATOM_SCALER_CENTER;
break;
case RMX_ASPECT:
args.ucEnable = ATOM_SCALER_EXPANSION;
break;
default:
if (ASIC_IS_AVIVO(rdev))
args.ucEnable = ATOM_SCALER_DISABLE;
else
args.ucEnable = ATOM_SCALER_CENTER;
break;
}
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
atom_rv515_force_tv_scaler(rdev);
}
}
static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
...@@ -203,6 +329,12 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) ...@@ -203,6 +329,12 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
if (ASIC_IS_AVIVO(rdev)) { if (ASIC_IS_AVIVO(rdev)) {
uint32_t ss_cntl; uint32_t ss_cntl;
if ((rdev->family == CHIP_RS600) ||
(rdev->family == CHIP_RS690) ||
(rdev->family == CHIP_RS740))
pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
RADEON_PLL_PREFER_CLOSEST_LOWER);
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
else else
...@@ -321,7 +453,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -321,7 +453,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv; struct drm_radeon_gem_object *obj_priv;
uint64_t fb_location; uint64_t fb_location;
uint32_t fb_format, fb_pitch_pixels; uint32_t fb_format, fb_pitch_pixels, tiling_flags;
if (!crtc->fb) if (!crtc->fb)
return -EINVAL; return -EINVAL;
...@@ -358,7 +490,14 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, ...@@ -358,7 +490,14 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
return -EINVAL; return -EINVAL;
} }
/* TODO tiling */ radeon_object_get_tiling_flags(obj->driver_private,
&tiling_flags, NULL);
if (tiling_flags & RADEON_TILING_MACRO)
fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
if (tiling_flags & RADEON_TILING_MICRO)
fb_format |= AVIVO_D1GRPH_TILED;
if (radeon_crtc->crtc_id == 0) if (radeon_crtc->crtc_id == 0)
WREG32(AVIVO_D1VGA_CONTROL, 0); WREG32(AVIVO_D1VGA_CONTROL, 0);
else else
...@@ -509,6 +648,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, ...@@ -509,6 +648,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
radeon_crtc_set_base(crtc, x, y, old_fb); radeon_crtc_set_base(crtc, x, y, old_fb);
radeon_legacy_atom_set_surface(crtc); radeon_legacy_atom_set_surface(crtc);
} }
atombios_overscan_setup(crtc, mode, adjusted_mode);
atombios_scaler_setup(crtc);
radeon_bandwidth_update(rdev);
return 0; return 0;
} }
...@@ -516,6 +658,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, ...@@ -516,6 +658,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
return false;
return true; return true;
} }
...@@ -548,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev, ...@@ -548,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
} }
void radeon_init_disp_bw_avivo(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2)
{
struct radeon_device *rdev = dev->dev_private;
fixed20_12 min_mem_eff;
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
fixed20_12 sclk_ff, mclk_ff;
uint32_t dc_lb_memory_split, temp;
min_mem_eff.full = rfixed_const_8(0);
if (rdev->disp_priority == 2) {
uint32_t mc_init_misc_lat_timer = 0;
if (rdev->family == CHIP_RV515)
mc_init_misc_lat_timer =
RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
else if (rdev->family == CHIP_RS690)
mc_init_misc_lat_timer =
RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);
mc_init_misc_lat_timer &=
~(R300_MC_DISP1R_INIT_LAT_MASK <<
R300_MC_DISP1R_INIT_LAT_SHIFT);
mc_init_misc_lat_timer &=
~(R300_MC_DISP0R_INIT_LAT_MASK <<
R300_MC_DISP0R_INIT_LAT_SHIFT);
if (mode2)
mc_init_misc_lat_timer |=
(1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
if (mode1)
mc_init_misc_lat_timer |=
(1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
if (rdev->family == CHIP_RV515)
WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
mc_init_misc_lat_timer);
else if (rdev->family == CHIP_RS690)
WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
mc_init_misc_lat_timer);
}
/*
* determine is there is enough bw for current mode
*/
temp_ff.full = rfixed_const(100);
mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
temp_ff.full = rfixed_const(temp);
mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
pix_clk.full = 0;
pix_clk2.full = 0;
peak_disp_bw.full = 0;
if (mode1) {
temp_ff.full = rfixed_const(1000);
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
pix_clk.full = rfixed_div(pix_clk, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes1);
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
}
if (mode2) {
temp_ff.full = rfixed_const(1000);
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes2);
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
}
if (peak_disp_bw.full >= mem_bw.full) {
DRM_ERROR
("You may not have enough display bandwidth for current mode\n"
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
printk("peak disp bw %d, mem_bw %d\n",
rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
}
/*
* Line Buffer Setup
* There is a single line buffer shared by both display controllers.
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
* controllers. The paritioning can either be done manually or via one of four
* preset allocations specified in bits 1:0:
* 0 - line buffer is divided in half and shared between each display controller
* 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
* 2 - D1 gets the whole buffer
* 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
* Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
* In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
* 14:4; D2 allocation follows D1.
*/
/* is auto or manual better ? */
dc_lb_memory_split =
RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
#if 1
/* auto */
if (mode1 && mode2) {
if (mode1->hdisplay > mode2->hdisplay) {
if (mode1->hdisplay > 2560)
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode2->hdisplay > mode1->hdisplay) {
if (mode2->hdisplay > 2560)
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode1) {
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
} else if (mode2) {
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
}
#else
/* manual */
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
dc_lb_memory_split &=
~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
if (mode1) {
dc_lb_memory_split |=
((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
<< AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
} else if (mode2) {
dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
}
#endif
WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
}
此差异已折叠。
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "drm.h" #include "drm.h"
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "radeon_drm.h"
#include "radeon_share.h"
/* r300,r350,rv350,rv370,rv380 depends on : */ /* r300,r350,rv350,rv370,rv380 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); void r100_hdp_reset(struct radeon_device *rdev);
...@@ -44,6 +46,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev); ...@@ -44,6 +46,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev);
int r100_cs_packet_parse(struct radeon_cs_parser *p, int r100_cs_packet_parse(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx); unsigned idx);
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc); struct radeon_cs_reloc **cs_reloc);
int r100_cs_parse_packet0(struct radeon_cs_parser *p, int r100_cs_parse_packet0(struct radeon_cs_parser *p,
...@@ -150,8 +153,13 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) ...@@ -150,8 +153,13 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
} }
addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC; addr = (lower_32_bits(addr) >> 8) |
writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4)); ((upper_32_bits(addr) & 0xff) << 24) |
0xc;
/* on x86 we want this to be CPU endian, on powerpc
* on powerpc without HW swappers, it'll get swapped on way
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
writel(addr, ((void __iomem *)ptr) + (i * 4));
return 0; return 0;
} }
...@@ -579,10 +587,8 @@ void r300_vram_info(struct radeon_device *rdev) ...@@ -579,10 +587,8 @@ void r300_vram_info(struct radeon_device *rdev)
} else { } else {
rdev->mc.vram_width = 64; rdev->mc.vram_width = 64;
} }
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); r100_vram_init_sizes(rdev);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
} }
...@@ -970,7 +976,7 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track) ...@@ -970,7 +976,7 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track)
static const unsigned r300_reg_safe_bm[159] = { static const unsigned r300_reg_safe_bm[159] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
...@@ -1019,7 +1025,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1019,7 +1025,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r300_cs_track *track; struct r300_cs_track *track;
volatile uint32_t *ib; volatile uint32_t *ib;
uint32_t tmp; uint32_t tmp, tile_flags = 0;
unsigned i; unsigned i;
int r; int r;
...@@ -1027,6 +1033,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1027,6 +1033,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
ib_chunk = &p->chunks[p->chunk_ib_idx]; ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r300_cs_track*)p->track; track = (struct r300_cs_track*)p->track;
switch(reg) { switch(reg) {
case AVIVO_D1MODE_VLINE_START_END:
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
break;
case RADEON_DST_PITCH_OFFSET: case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET: case RADEON_SRC_PITCH_OFFSET:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -1038,7 +1054,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1038,7 +1054,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
} }
tmp = ib_chunk->kdata[idx] & 0x003fffff; tmp = ib_chunk->kdata[idx] & 0x003fffff;
tmp += (((u32)reloc->lobj.gpu_offset) >> 10); tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= RADEON_DST_TILE_MACRO;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
if (reg == RADEON_SRC_PITCH_OFFSET) {
DRM_ERROR("Cannot src blit from microtiled surface\n");
r100_cs_dump_packet(p, pkt);
return -EINVAL;
}
tile_flags |= RADEON_DST_TILE_MICRO;
}
tmp |= tile_flags;
ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
break; break;
case R300_RB3D_COLOROFFSET0: case R300_RB3D_COLOROFFSET0:
case R300_RB3D_COLOROFFSET1: case R300_RB3D_COLOROFFSET1:
...@@ -1127,6 +1155,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1127,6 +1155,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
/* RB3D_COLORPITCH1 */ /* RB3D_COLORPITCH1 */
/* RB3D_COLORPITCH2 */ /* RB3D_COLORPITCH2 */
/* RB3D_COLORPITCH3 */ /* RB3D_COLORPITCH3 */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= R300_COLOR_TILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_COLOR_MICROTILE_ENABLE;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
i = (reg - 0x4E38) >> 2; i = (reg - 0x4E38) >> 2;
track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
...@@ -1182,6 +1227,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1182,6 +1227,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
break; break;
case 0x4F24: case 0x4F24:
/* ZB_DEPTHPITCH */ /* ZB_DEPTHPITCH */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= R300_DEPTHMACROTILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_DEPTHMICROTILE_TILED;;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
break; break;
case 0x4104: case 0x4104:
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#ifndef _R300_REG_H_ #ifndef _R300_REG_H_
#define _R300_REG_H_ #define _R300_REG_H_
#define R300_SURF_TILE_MACRO (1<<16)
#define R300_SURF_TILE_MICRO (2<<16)
#define R300_SURF_TILE_BOTH (3<<16)
#define R300_MC_INIT_MISC_LAT_TIMER 0x180 #define R300_MC_INIT_MISC_LAT_TIMER 0x180
......
...@@ -445,6 +445,7 @@ ...@@ -445,6 +445,7 @@
#define AVIVO_D1MODE_DATA_FORMAT 0x6528 #define AVIVO_D1MODE_DATA_FORMAT 0x6528
# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) # define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C #define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C
#define AVIVO_D1MODE_VLINE_START_END 0x6538
#define AVIVO_D1MODE_VIEWPORT_START 0x6580 #define AVIVO_D1MODE_VIEWPORT_START 0x6580
#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 #define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588
...@@ -496,6 +497,7 @@ ...@@ -496,6 +497,7 @@
#define AVIVO_D2CUR_SIZE 0x6c10 #define AVIVO_D2CUR_SIZE 0x6c10
#define AVIVO_D2CUR_POSITION 0x6c14 #define AVIVO_D2CUR_POSITION 0x6c14
#define AVIVO_D2MODE_VLINE_START_END 0x6d38
#define AVIVO_D2MODE_VIEWPORT_START 0x6d80 #define AVIVO_D2MODE_VIEWPORT_START 0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84
#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "drmP.h" #include "drmP.h"
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "radeon_share.h"
/* r520,rv530,rv560,rv570,r580 depends on : */ /* r520,rv530,rv560,rv570,r580 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); void r100_hdp_reset(struct radeon_device *rdev);
...@@ -94,8 +95,8 @@ int r520_mc_init(struct radeon_device *rdev) ...@@ -94,8 +95,8 @@ int r520_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
/* Write VRAM size in case we are limiting it */ /* Write VRAM size in case we are limiting it */
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16); tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16); tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(R520_MC_FB_LOCATION, tmp); WREG32_MC(R520_MC_FB_LOCATION, tmp);
...@@ -226,9 +227,20 @@ static void r520_vram_get_type(struct radeon_device *rdev) ...@@ -226,9 +227,20 @@ static void r520_vram_get_type(struct radeon_device *rdev)
void r520_vram_info(struct radeon_device *rdev) void r520_vram_info(struct radeon_device *rdev)
{ {
fixed20_12 a;
r520_vram_get_type(rdev); r520_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); r100_vram_init_sizes(rdev);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); /* FIXME: we should enforce default clock in case GPU is not in
* default setup
*/
a.full = rfixed_const(100);
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
}
void r520_bandwidth_update(struct radeon_device *rdev)
{
rv515_bandwidth_avivo_update(rdev);
} }
...@@ -67,7 +67,7 @@ int r600_mc_init(struct radeon_device *rdev) ...@@ -67,7 +67,7 @@ int r600_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24); tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24);
tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24); tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24);
WREG32(R600_MC_VM_FB_LOCATION, tmp); WREG32(R600_MC_VM_FB_LOCATION, tmp);
...@@ -140,7 +140,8 @@ void r600_vram_get_type(struct radeon_device *rdev) ...@@ -140,7 +140,8 @@ void r600_vram_get_type(struct radeon_device *rdev)
void r600_vram_info(struct radeon_device *rdev) void r600_vram_info(struct radeon_device *rdev)
{ {
r600_vram_get_type(rdev); r600_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
/* Could aper size report 0 ? */ /* Could aper size report 0 ? */
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
......
...@@ -64,6 +64,7 @@ extern int radeon_agpmode; ...@@ -64,6 +64,7 @@ extern int radeon_agpmode;
extern int radeon_vram_limit; extern int radeon_vram_limit;
extern int radeon_gart_size; extern int radeon_gart_size;
extern int radeon_benchmarking; extern int radeon_benchmarking;
extern int radeon_testing;
extern int radeon_connector_table; extern int radeon_connector_table;
/* /*
...@@ -113,6 +114,7 @@ enum radeon_family { ...@@ -113,6 +114,7 @@ enum radeon_family {
CHIP_RV770, CHIP_RV770,
CHIP_RV730, CHIP_RV730,
CHIP_RV710, CHIP_RV710,
CHIP_RS880,
CHIP_LAST, CHIP_LAST,
}; };
...@@ -201,6 +203,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev); ...@@ -201,6 +203,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev);
struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
void radeon_fence_unref(struct radeon_fence **fence); void radeon_fence_unref(struct radeon_fence **fence);
/*
* Tiling registers
*/
struct radeon_surface_reg {
struct radeon_object *robj;
};
#define RADEON_GEM_MAX_SURFACES 8
/* /*
* Radeon buffer. * Radeon buffer.
...@@ -213,6 +223,7 @@ struct radeon_object_list { ...@@ -213,6 +223,7 @@ struct radeon_object_list {
uint64_t gpu_offset; uint64_t gpu_offset;
unsigned rdomain; unsigned rdomain;
unsigned wdomain; unsigned wdomain;
uint32_t tiling_flags;
}; };
int radeon_object_init(struct radeon_device *rdev); int radeon_object_init(struct radeon_device *rdev);
...@@ -242,8 +253,15 @@ void radeon_object_list_clean(struct list_head *head); ...@@ -242,8 +253,15 @@ void radeon_object_list_clean(struct list_head *head);
int radeon_object_fbdev_mmap(struct radeon_object *robj, int radeon_object_fbdev_mmap(struct radeon_object *robj,
struct vm_area_struct *vma); struct vm_area_struct *vma);
unsigned long radeon_object_size(struct radeon_object *robj); unsigned long radeon_object_size(struct radeon_object *robj);
void radeon_object_clear_surface_reg(struct radeon_object *robj);
int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
bool force_drop);
void radeon_object_set_tiling_flags(struct radeon_object *robj,
uint32_t tiling_flags, uint32_t pitch);
void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch);
void radeon_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem);
void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
/* /*
* GEM objects. * GEM objects.
*/ */
...@@ -315,8 +333,11 @@ struct radeon_mc { ...@@ -315,8 +333,11 @@ struct radeon_mc {
unsigned gtt_location; unsigned gtt_location;
unsigned gtt_size; unsigned gtt_size;
unsigned vram_location; unsigned vram_location;
unsigned vram_size; /* for some chips with <= 32MB we need to lie
* about vram size near mc fb location */
unsigned mc_vram_size;
unsigned vram_width; unsigned vram_width;
unsigned real_vram_size;
int vram_mtrr; int vram_mtrr;
bool vram_is_ddr; bool vram_is_ddr;
}; };
...@@ -474,6 +495,39 @@ struct radeon_wb { ...@@ -474,6 +495,39 @@ struct radeon_wb {
uint64_t gpu_addr; uint64_t gpu_addr;
}; };
/**
* struct radeon_pm - power management datas
* @max_bandwidth: maximum bandwidth the gpu has (MByte/s)
* @igp_sideport_mclk: sideport memory clock Mhz (rs690,rs740,rs780,rs880)
* @igp_system_mclk: system clock Mhz (rs690,rs740,rs780,rs880)
* @igp_ht_link_clk: ht link clock Mhz (rs690,rs740,rs780,rs880)
* @igp_ht_link_width: ht link width in bits (rs690,rs740,rs780,rs880)
* @k8_bandwidth: k8 bandwidth the gpu has (MByte/s) (IGP)
* @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP)
* @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP)
* @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP)
* @sclk: GPU clock Mhz (core bandwith depends of this clock)
* @needed_bandwidth: current bandwidth needs
*
* It keeps track of various data needed to take powermanagement decision.
* Bandwith need is used to determine minimun clock of the GPU and memory.
* Equation between gpu/memory clock and available bandwidth is hw dependent
* (type of memory, bus size, efficiency, ...)
*/
struct radeon_pm {
fixed20_12 max_bandwidth;
fixed20_12 igp_sideport_mclk;
fixed20_12 igp_system_mclk;
fixed20_12 igp_ht_link_clk;
fixed20_12 igp_ht_link_width;
fixed20_12 k8_bandwidth;
fixed20_12 sideport_bandwidth;
fixed20_12 ht_bandwidth;
fixed20_12 core_bandwidth;
fixed20_12 sclk;
fixed20_12 needed_bandwidth;
};
/* /*
* Benchmarking * Benchmarking
...@@ -481,6 +535,12 @@ struct radeon_wb { ...@@ -481,6 +535,12 @@ struct radeon_wb {
void radeon_benchmark(struct radeon_device *rdev); void radeon_benchmark(struct radeon_device *rdev);
/*
* Testing
*/
void radeon_test_moves(struct radeon_device *rdev);
/* /*
* Debugfs * Debugfs
*/ */
...@@ -535,6 +595,11 @@ struct radeon_asic { ...@@ -535,6 +595,11 @@ struct radeon_asic {
void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
void (*set_clock_gating)(struct radeon_device *rdev, int enable); void (*set_clock_gating)(struct radeon_device *rdev, int enable);
int (*set_surface_reg)(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
void (*bandwidth_update)(struct radeon_device *rdev);
}; };
union radeon_asic_config { union radeon_asic_config {
...@@ -566,6 +631,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, ...@@ -566,6 +631,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp); struct drm_file *filp);
int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
/* /*
...@@ -594,8 +663,8 @@ struct radeon_device { ...@@ -594,8 +663,8 @@ struct radeon_device {
struct radeon_object *fbdev_robj; struct radeon_object *fbdev_robj;
struct radeon_framebuffer *fbdev_rfb; struct radeon_framebuffer *fbdev_rfb;
/* Register mmio */ /* Register mmio */
unsigned long rmmio_base; resource_size_t rmmio_base;
unsigned long rmmio_size; resource_size_t rmmio_size;
void *rmmio; void *rmmio;
radeon_rreg_t mm_rreg; radeon_rreg_t mm_rreg;
radeon_wreg_t mm_wreg; radeon_wreg_t mm_wreg;
...@@ -619,11 +688,14 @@ struct radeon_device { ...@@ -619,11 +688,14 @@ struct radeon_device {
struct radeon_irq irq; struct radeon_irq irq;
struct radeon_asic *asic; struct radeon_asic *asic;
struct radeon_gem gem; struct radeon_gem gem;
struct radeon_pm pm;
struct mutex cs_mutex; struct mutex cs_mutex;
struct radeon_wb wb; struct radeon_wb wb;
bool gpu_lockup; bool gpu_lockup;
bool shutdown; bool shutdown;
bool suspend; bool suspend;
bool need_dma32;
struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
}; };
int radeon_device_init(struct radeon_device *rdev, int radeon_device_init(struct radeon_device *rdev,
...@@ -670,6 +742,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); ...@@ -670,6 +742,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
/* /*
* ASICs helpers. * ASICs helpers.
*/ */
#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \
(rdev->pdev->device == 0x5969))
#define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \ #define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \
(rdev->family == CHIP_RV200) || \ (rdev->family == CHIP_RV200) || \
(rdev->family == CHIP_RS100) || \ (rdev->family == CHIP_RS100) || \
...@@ -796,5 +870,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) ...@@ -796,5 +870,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
#endif #endif
...@@ -71,6 +71,11 @@ int r100_copy_blit(struct radeon_device *rdev, ...@@ -71,6 +71,11 @@ int r100_copy_blit(struct radeon_device *rdev,
uint64_t dst_offset, uint64_t dst_offset,
unsigned num_pages, unsigned num_pages,
struct radeon_fence *fence); struct radeon_fence *fence);
int r100_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
void r100_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic r100_asic = { static struct radeon_asic r100_asic = {
.init = &r100_init, .init = &r100_init,
...@@ -100,6 +105,9 @@ static struct radeon_asic r100_asic = { ...@@ -100,6 +105,9 @@ static struct radeon_asic r100_asic = {
.set_memory_clock = NULL, .set_memory_clock = NULL,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_legacy_set_clock_gating, .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
...@@ -128,6 +136,7 @@ int r300_copy_dma(struct radeon_device *rdev, ...@@ -128,6 +136,7 @@ int r300_copy_dma(struct radeon_device *rdev,
uint64_t dst_offset, uint64_t dst_offset,
unsigned num_pages, unsigned num_pages,
struct radeon_fence *fence); struct radeon_fence *fence);
static struct radeon_asic r300_asic = { static struct radeon_asic r300_asic = {
.init = &r300_init, .init = &r300_init,
.errata = &r300_errata, .errata = &r300_errata,
...@@ -156,6 +165,9 @@ static struct radeon_asic r300_asic = { ...@@ -156,6 +165,9 @@ static struct radeon_asic r300_asic = {
.set_memory_clock = NULL, .set_memory_clock = NULL,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_legacy_set_clock_gating, .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
/* /*
...@@ -193,6 +205,9 @@ static struct radeon_asic r420_asic = { ...@@ -193,6 +205,9 @@ static struct radeon_asic r420_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
...@@ -237,6 +252,9 @@ static struct radeon_asic rs400_asic = { ...@@ -237,6 +252,9 @@ static struct radeon_asic rs400_asic = {
.set_memory_clock = NULL, .set_memory_clock = NULL,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_legacy_set_clock_gating, .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
...@@ -254,6 +272,7 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev); ...@@ -254,6 +272,7 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev);
int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rs600_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rs600_asic = { static struct radeon_asic rs600_asic = {
.init = &r300_init, .init = &r300_init,
.errata = &rs600_errata, .errata = &rs600_errata,
...@@ -282,6 +301,7 @@ static struct radeon_asic rs600_asic = { ...@@ -282,6 +301,7 @@ static struct radeon_asic rs600_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.bandwidth_update = &rs600_bandwidth_update,
}; };
...@@ -294,6 +314,7 @@ int rs690_mc_init(struct radeon_device *rdev); ...@@ -294,6 +314,7 @@ int rs690_mc_init(struct radeon_device *rdev);
void rs690_mc_fini(struct radeon_device *rdev); void rs690_mc_fini(struct radeon_device *rdev);
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rs690_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rs690_asic = { static struct radeon_asic rs690_asic = {
.init = &r300_init, .init = &r300_init,
.errata = &rs690_errata, .errata = &rs690_errata,
...@@ -322,6 +343,9 @@ static struct radeon_asic rs690_asic = { ...@@ -322,6 +343,9 @@ static struct radeon_asic rs690_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rs690_bandwidth_update,
}; };
...@@ -339,6 +363,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); ...@@ -339,6 +363,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_ring_start(struct radeon_device *rdev); void rv515_ring_start(struct radeon_device *rdev);
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rv515_asic = { static struct radeon_asic rv515_asic = {
.init = &rv515_init, .init = &rv515_init,
.errata = &rv515_errata, .errata = &rv515_errata,
...@@ -367,6 +392,9 @@ static struct radeon_asic rv515_asic = { ...@@ -367,6 +392,9 @@ static struct radeon_asic rv515_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
}; };
...@@ -377,6 +405,7 @@ void r520_errata(struct radeon_device *rdev); ...@@ -377,6 +405,7 @@ void r520_errata(struct radeon_device *rdev);
void r520_vram_info(struct radeon_device *rdev); void r520_vram_info(struct radeon_device *rdev);
int r520_mc_init(struct radeon_device *rdev); int r520_mc_init(struct radeon_device *rdev);
void r520_mc_fini(struct radeon_device *rdev); void r520_mc_fini(struct radeon_device *rdev);
void r520_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic r520_asic = { static struct radeon_asic r520_asic = {
.init = &rv515_init, .init = &rv515_init,
.errata = &r520_errata, .errata = &r520_errata,
...@@ -405,6 +434,9 @@ static struct radeon_asic r520_asic = { ...@@ -405,6 +434,9 @@ static struct radeon_asic r520_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r520_bandwidth_update,
}; };
/* /*
......
...@@ -103,7 +103,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device ...@@ -103,7 +103,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
static bool radeon_atom_apply_quirks(struct drm_device *dev, static bool radeon_atom_apply_quirks(struct drm_device *dev,
uint32_t supported_device, uint32_t supported_device,
int *connector_type, int *connector_type,
struct radeon_i2c_bus_rec *i2c_bus) struct radeon_i2c_bus_rec *i2c_bus,
uint8_t *line_mux)
{ {
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */ /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
...@@ -127,8 +128,10 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, ...@@ -127,8 +128,10 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
if ((dev->pdev->device == 0x5653) && if ((dev->pdev->device == 0x5653) &&
(dev->pdev->subsystem_vendor == 0x1462) && (dev->pdev->subsystem_vendor == 0x1462) &&
(dev->pdev->subsystem_device == 0x0291)) { (dev->pdev->subsystem_device == 0x0291)) {
if (*connector_type == DRM_MODE_CONNECTOR_LVDS) if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
i2c_bus->valid = false; i2c_bus->valid = false;
*line_mux = 53;
}
} }
/* Funky macbooks */ /* Funky macbooks */
...@@ -526,7 +529,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct ...@@ -526,7 +529,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
if (!radeon_atom_apply_quirks if (!radeon_atom_apply_quirks
(dev, (1 << i), &bios_connectors[i].connector_type, (dev, (1 << i), &bios_connectors[i].connector_type,
&bios_connectors[i].ddc_bus)) &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
continue; continue;
bios_connectors[i].valid = true; bios_connectors[i].valid = true;
......
...@@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, ...@@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
r = radeon_copy_dma(rdev, saddr, daddr, size >> 14, fence); r = radeon_copy_dma(rdev, saddr, daddr, size / 4096, fence);
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
...@@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, ...@@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
r = radeon_copy_blit(rdev, saddr, daddr, size >> 14, fence); r = radeon_copy_blit(rdev, saddr, daddr, size / 4096, fence);
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
......
...@@ -127,17 +127,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) ...@@ -127,17 +127,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
sizeof(struct drm_radeon_cs_chunk))) { sizeof(struct drm_radeon_cs_chunk))) {
return -EFAULT; return -EFAULT;
} }
p->chunks[i].length_dw = user_chunk.length_dw;
p->chunks[i].kdata = NULL;
p->chunks[i].chunk_id = user_chunk.chunk_id; p->chunks[i].chunk_id = user_chunk.chunk_id;
if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) { if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) {
p->chunk_relocs_idx = i; p->chunk_relocs_idx = i;
} }
if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) { if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) {
p->chunk_ib_idx = i; p->chunk_ib_idx = i;
/* zero length IB isn't useful */
if (p->chunks[i].length_dw == 0)
return -EINVAL;
} }
p->chunks[i].length_dw = user_chunk.length_dw; p->chunks[i].length_dw = user_chunk.length_dw;
cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
p->chunks[i].kdata = NULL;
size = p->chunks[i].length_dw * sizeof(uint32_t); size = p->chunks[i].length_dw * sizeof(uint32_t);
p->chunks[i].kdata = kzalloc(size, GFP_KERNEL); p->chunks[i].kdata = kzalloc(size, GFP_KERNEL);
if (p->chunks[i].kdata == NULL) { if (p->chunks[i].kdata == NULL) {
......
...@@ -111,9 +111,11 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, ...@@ -111,9 +111,11 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
if (ASIC_IS_AVIVO(rdev)) if (ASIC_IS_AVIVO(rdev))
WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
else else {
radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
/* offset is from DISP(2)_BASE_ADDRESS */ /* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, gpu_addr); WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
}
} }
int radeon_crtc_cursor_set(struct drm_crtc *crtc, int radeon_crtc_cursor_set(struct drm_crtc *crtc,
...@@ -245,6 +247,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, ...@@ -245,6 +247,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
(RADEON_CUR_LOCK (RADEON_CUR_LOCK
| ((xorigin ? 0 : x) << 16) | ((xorigin ? 0 : x) << 16)
| (yorigin ? 0 : y))); | (yorigin ? 0 : y)));
/* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
(yorigin * 256)));
} }
radeon_lock_cursor(crtc, false); radeon_lock_cursor(crtc, false);
......
...@@ -48,6 +48,8 @@ static void radeon_surface_init(struct radeon_device *rdev) ...@@ -48,6 +48,8 @@ static void radeon_surface_init(struct radeon_device *rdev)
i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
0); 0);
} }
/* enable surfaces */
WREG32(RADEON_SURFACE_CNTL, 0);
} }
} }
...@@ -119,7 +121,7 @@ int radeon_mc_setup(struct radeon_device *rdev) ...@@ -119,7 +121,7 @@ int radeon_mc_setup(struct radeon_device *rdev)
if (rdev->mc.vram_location != 0xFFFFFFFFUL) { if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
/* vram location was already setup try to put gtt after /* vram location was already setup try to put gtt after
* if it fits */ * if it fits */
tmp = rdev->mc.vram_location + rdev->mc.vram_size; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
rdev->mc.gtt_location = tmp; rdev->mc.gtt_location = tmp;
...@@ -134,13 +136,13 @@ int radeon_mc_setup(struct radeon_device *rdev) ...@@ -134,13 +136,13 @@ int radeon_mc_setup(struct radeon_device *rdev)
} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
/* gtt location was already setup try to put vram before /* gtt location was already setup try to put vram before
* if it fits */ * if it fits */
if (rdev->mc.vram_size < rdev->mc.gtt_location) { if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
rdev->mc.vram_location = 0; rdev->mc.vram_location = 0;
} else { } else {
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
tmp += (rdev->mc.vram_size - 1); tmp += (rdev->mc.mc_vram_size - 1);
tmp &= ~(rdev->mc.vram_size - 1); tmp &= ~(rdev->mc.mc_vram_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
rdev->mc.vram_location = tmp; rdev->mc.vram_location = tmp;
} else { } else {
printk(KERN_ERR "[drm] vram too big to fit " printk(KERN_ERR "[drm] vram too big to fit "
...@@ -150,12 +152,14 @@ int radeon_mc_setup(struct radeon_device *rdev) ...@@ -150,12 +152,14 @@ int radeon_mc_setup(struct radeon_device *rdev)
} }
} else { } else {
rdev->mc.vram_location = 0; rdev->mc.vram_location = 0;
rdev->mc.gtt_location = rdev->mc.vram_size; rdev->mc.gtt_location = rdev->mc.mc_vram_size;
} }
DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20);
DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
rdev->mc.vram_location, rdev->mc.vram_location,
rdev->mc.vram_location + rdev->mc.vram_size - 1); rdev->mc.vram_location + rdev->mc.mc_vram_size - 1);
if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size)
DRM_INFO("radeon: VRAM less than aperture workaround enabled\n");
DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20);
DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
rdev->mc.gtt_location, rdev->mc.gtt_location,
...@@ -450,6 +454,7 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -450,6 +454,7 @@ int radeon_device_init(struct radeon_device *rdev,
uint32_t flags) uint32_t flags)
{ {
int r, ret; int r, ret;
int dma_bits;
DRM_INFO("radeon: Initializing kernel modesetting.\n"); DRM_INFO("radeon: Initializing kernel modesetting.\n");
rdev->shutdown = false; rdev->shutdown = false;
...@@ -492,8 +497,20 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -492,8 +497,20 @@ int radeon_device_init(struct radeon_device *rdev,
return r; return r;
} }
/* Report DMA addressing limitation */ /* set DMA mask + need_dma32 flags.
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); * PCIE - can handle 40-bits.
* IGP - can handle 40-bits (in theory)
* AGP - generally dma32 is safest
* PCI - only dma32
*/
rdev->need_dma32 = false;
if (rdev->flags & RADEON_IS_AGP)
rdev->need_dma32 = true;
if (rdev->flags & RADEON_IS_PCI)
rdev->need_dma32 = true;
dma_bits = rdev->need_dma32 ? 32 : 40;
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
if (r) { if (r) {
printk(KERN_WARNING "radeon: No suitable DMA available.\n"); printk(KERN_WARNING "radeon: No suitable DMA available.\n");
} }
...@@ -546,27 +563,22 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -546,27 +563,22 @@ int radeon_device_init(struct radeon_device *rdev,
radeon_combios_asic_init(rdev->ddev); radeon_combios_asic_init(rdev->ddev);
} }
} }
/* Initialize clocks */
r = radeon_clocks_init(rdev);
if (r) {
return r;
}
/* Get vram informations */ /* Get vram informations */
radeon_vram_info(rdev); radeon_vram_info(rdev);
/* Device is severly broken if aper size > vram size.
* for RN50/M6/M7 - Novell bug 204882 ?
*/
if (rdev->mc.vram_size < rdev->mc.aper_size) {
rdev->mc.aper_size = rdev->mc.vram_size;
}
/* Add an MTRR for the VRAM */ /* Add an MTRR for the VRAM */
rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
MTRR_TYPE_WRCOMB, 1); MTRR_TYPE_WRCOMB, 1);
DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n",
rdev->mc.vram_size >> 20, rdev->mc.real_vram_size >> 20,
(unsigned)rdev->mc.aper_size >> 20); (unsigned)rdev->mc.aper_size >> 20);
DRM_INFO("RAM width %dbits %cDR\n", DRM_INFO("RAM width %dbits %cDR\n",
rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
/* Initialize clocks */
r = radeon_clocks_init(rdev);
if (r) {
return r;
}
/* Initialize memory controller (also test AGP) */ /* Initialize memory controller (also test AGP) */
r = radeon_mc_init(rdev); r = radeon_mc_init(rdev);
if (r) { if (r) {
...@@ -626,6 +638,9 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -626,6 +638,9 @@ int radeon_device_init(struct radeon_device *rdev,
if (!ret) { if (!ret) {
DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
} }
if (radeon_testing) {
radeon_test_moves(rdev);
}
if (radeon_benchmarking) { if (radeon_benchmarking) {
radeon_benchmark(rdev); radeon_benchmark(rdev);
} }
......
...@@ -187,6 +187,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) ...@@ -187,6 +187,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
radeon_crtc->crtc_id = index; radeon_crtc->crtc_id = index;
rdev->mode_info.crtcs[index] = radeon_crtc;
radeon_crtc->mode_set.crtc = &radeon_crtc->base; radeon_crtc->mode_set.crtc = &radeon_crtc->base;
radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1); radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
...@@ -491,7 +492,11 @@ void radeon_compute_pll(struct radeon_pll *pll, ...@@ -491,7 +492,11 @@ void radeon_compute_pll(struct radeon_pll *pll,
tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
current_freq = radeon_div(tmp, ref_div * post_div); current_freq = radeon_div(tmp, ref_div * post_div);
error = abs(current_freq - freq); if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
error = freq - current_freq;
error = error < 0 ? 0xffffffff : error;
} else
error = abs(current_freq - freq);
vco_diff = abs(vco - best_vco); vco_diff = abs(vco - best_vco);
if ((best_vco == 0 && error < best_error) || if ((best_vco == 0 && error < best_error) ||
...@@ -657,36 +662,51 @@ void radeon_modeset_fini(struct radeon_device *rdev) ...@@ -657,36 +662,51 @@ void radeon_modeset_fini(struct radeon_device *rdev)
} }
} }
void radeon_init_disp_bandwidth(struct drm_device *dev) bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{ {
struct radeon_device *rdev = dev->dev_private; struct drm_device *dev = crtc->dev;
struct drm_display_mode *modes[2]; struct drm_encoder *encoder;
int pixel_bytes[2]; struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_crtc *crtc; struct radeon_encoder *radeon_encoder;
bool first = true;
pixel_bytes[0] = pixel_bytes[1] = 0;
modes[0] = modes[1] = NULL;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
if (crtc->enabled && crtc->fb) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
modes[radeon_crtc->crtc_id] = &crtc->mode; radeon_encoder = to_radeon_encoder(encoder);
pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8; if (encoder->crtc != crtc)
continue;
if (first) {
radeon_crtc->rmx_type = radeon_encoder->rmx_type;
radeon_crtc->devices = radeon_encoder->devices;
memcpy(&radeon_crtc->native_mode,
&radeon_encoder->native_mode,
sizeof(struct radeon_native_mode));
first = false;
} else {
if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
/* WARNING: Right now this can't happen but
* in the future we need to check that scaling
* are consistent accross different encoder
* (ie all encoder can work with the same
* scaling).
*/
DRM_ERROR("Scaling not consistent accross encoder.\n");
return false;
}
} }
} }
if (radeon_crtc->rmx_type != RMX_OFF) {
if (ASIC_IS_AVIVO(rdev)) { fixed20_12 a, b;
radeon_init_disp_bw_avivo(dev, a.full = rfixed_const(crtc->mode.vdisplay);
modes[0], b.full = rfixed_const(radeon_crtc->native_mode.panel_xres);
pixel_bytes[0], radeon_crtc->vsc.full = rfixed_div(a, b);
modes[1], a.full = rfixed_const(crtc->mode.hdisplay);
pixel_bytes[1]); b.full = rfixed_const(radeon_crtc->native_mode.panel_yres);
radeon_crtc->hsc.full = rfixed_div(a, b);
} else { } else {
radeon_init_disp_bw_legacy(dev, radeon_crtc->vsc.full = rfixed_const(1);
modes[0], radeon_crtc->hsc.full = rfixed_const(1);
pixel_bytes[0],
modes[1],
pixel_bytes[1]);
} }
return true;
} }
...@@ -89,6 +89,7 @@ int radeon_agpmode = 0; ...@@ -89,6 +89,7 @@ int radeon_agpmode = 0;
int radeon_vram_limit = 0; int radeon_vram_limit = 0;
int radeon_gart_size = 512; /* default gart size */ int radeon_gart_size = 512; /* default gart size */
int radeon_benchmarking = 0; int radeon_benchmarking = 0;
int radeon_testing = 0;
int radeon_connector_table = 0; int radeon_connector_table = 0;
#endif #endif
...@@ -117,6 +118,9 @@ module_param_named(gartsize, radeon_gart_size, int, 0600); ...@@ -117,6 +118,9 @@ module_param_named(gartsize, radeon_gart_size, int, 0600);
MODULE_PARM_DESC(benchmark, "Run benchmark"); MODULE_PARM_DESC(benchmark, "Run benchmark");
module_param_named(benchmark, radeon_benchmarking, int, 0444); module_param_named(benchmark, radeon_benchmarking, int, 0444);
MODULE_PARM_DESC(test, "Run tests");
module_param_named(test, radeon_testing, int, 0444);
MODULE_PARM_DESC(connector_table, "Force connector table"); MODULE_PARM_DESC(connector_table, "Force connector table");
module_param_named(connector_table, radeon_connector_table, int, 0444); module_param_named(connector_table, radeon_connector_table, int, 0444);
#endif #endif
......
...@@ -154,7 +154,6 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder, ...@@ -154,7 +154,6 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
if (mode->hdisplay < native_mode->panel_xres || if (mode->hdisplay < native_mode->panel_xres ||
mode->vdisplay < native_mode->panel_yres) { mode->vdisplay < native_mode->panel_yres) {
radeon_encoder->flags |= RADEON_USE_RMX;
if (ASIC_IS_AVIVO(rdev)) { if (ASIC_IS_AVIVO(rdev)) {
adjusted_mode->hdisplay = native_mode->panel_xres; adjusted_mode->hdisplay = native_mode->panel_xres;
adjusted_mode->vdisplay = native_mode->panel_yres; adjusted_mode->vdisplay = native_mode->panel_yres;
...@@ -197,15 +196,13 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder, ...@@ -197,15 +196,13 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
} }
} }
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, static bool radeon_atom_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)
{ {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
radeon_encoder->flags &= ~RADEON_USE_RMX;
drm_mode_set_crtcinfo(adjusted_mode, 0); drm_mode_set_crtcinfo(adjusted_mode, 0);
if (radeon_encoder->rmx_type != RMX_OFF) if (radeon_encoder->rmx_type != RMX_OFF)
...@@ -808,234 +805,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) ...@@ -808,234 +805,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
} }
static void atom_rv515_force_tv_scaler(struct radeon_device *rdev)
{
WREG32(0x659C, 0x0);
WREG32(0x6594, 0x705);
WREG32(0x65A4, 0x10001);
WREG32(0x65D8, 0x0);
WREG32(0x65B0, 0x0);
WREG32(0x65C0, 0x0);
WREG32(0x65D4, 0x0);
WREG32(0x6578, 0x0);
WREG32(0x657C, 0x841880A8);
WREG32(0x6578, 0x1);
WREG32(0x657C, 0x84208680);
WREG32(0x6578, 0x2);
WREG32(0x657C, 0xBFF880B0);
WREG32(0x6578, 0x100);
WREG32(0x657C, 0x83D88088);
WREG32(0x6578, 0x101);
WREG32(0x657C, 0x84608680);
WREG32(0x6578, 0x102);
WREG32(0x657C, 0xBFF080D0);
WREG32(0x6578, 0x200);
WREG32(0x657C, 0x83988068);
WREG32(0x6578, 0x201);
WREG32(0x657C, 0x84A08680);
WREG32(0x6578, 0x202);
WREG32(0x657C, 0xBFF080F8);
WREG32(0x6578, 0x300);
WREG32(0x657C, 0x83588058);
WREG32(0x6578, 0x301);
WREG32(0x657C, 0x84E08660);
WREG32(0x6578, 0x302);
WREG32(0x657C, 0xBFF88120);
WREG32(0x6578, 0x400);
WREG32(0x657C, 0x83188040);
WREG32(0x6578, 0x401);
WREG32(0x657C, 0x85008660);
WREG32(0x6578, 0x402);
WREG32(0x657C, 0xBFF88150);
WREG32(0x6578, 0x500);
WREG32(0x657C, 0x82D88030);
WREG32(0x6578, 0x501);
WREG32(0x657C, 0x85408640);
WREG32(0x6578, 0x502);
WREG32(0x657C, 0xBFF88180);
WREG32(0x6578, 0x600);
WREG32(0x657C, 0x82A08018);
WREG32(0x6578, 0x601);
WREG32(0x657C, 0x85808620);
WREG32(0x6578, 0x602);
WREG32(0x657C, 0xBFF081B8);
WREG32(0x6578, 0x700);
WREG32(0x657C, 0x82608010);
WREG32(0x6578, 0x701);
WREG32(0x657C, 0x85A08600);
WREG32(0x6578, 0x702);
WREG32(0x657C, 0x800081F0);
WREG32(0x6578, 0x800);
WREG32(0x657C, 0x8228BFF8);
WREG32(0x6578, 0x801);
WREG32(0x657C, 0x85E085E0);
WREG32(0x6578, 0x802);
WREG32(0x657C, 0xBFF88228);
WREG32(0x6578, 0x10000);
WREG32(0x657C, 0x82A8BF00);
WREG32(0x6578, 0x10001);
WREG32(0x657C, 0x82A08CC0);
WREG32(0x6578, 0x10002);
WREG32(0x657C, 0x8008BEF8);
WREG32(0x6578, 0x10100);
WREG32(0x657C, 0x81F0BF28);
WREG32(0x6578, 0x10101);
WREG32(0x657C, 0x83608CA0);
WREG32(0x6578, 0x10102);
WREG32(0x657C, 0x8018BED0);
WREG32(0x6578, 0x10200);
WREG32(0x657C, 0x8148BF38);
WREG32(0x6578, 0x10201);
WREG32(0x657C, 0x84408C80);
WREG32(0x6578, 0x10202);
WREG32(0x657C, 0x8008BEB8);
WREG32(0x6578, 0x10300);
WREG32(0x657C, 0x80B0BF78);
WREG32(0x6578, 0x10301);
WREG32(0x657C, 0x85008C20);
WREG32(0x6578, 0x10302);
WREG32(0x657C, 0x8020BEA0);
WREG32(0x6578, 0x10400);
WREG32(0x657C, 0x8028BF90);
WREG32(0x6578, 0x10401);
WREG32(0x657C, 0x85E08BC0);
WREG32(0x6578, 0x10402);
WREG32(0x657C, 0x8018BE90);
WREG32(0x6578, 0x10500);
WREG32(0x657C, 0xBFB8BFB0);
WREG32(0x6578, 0x10501);
WREG32(0x657C, 0x86C08B40);
WREG32(0x6578, 0x10502);
WREG32(0x657C, 0x8010BE90);
WREG32(0x6578, 0x10600);
WREG32(0x657C, 0xBF58BFC8);
WREG32(0x6578, 0x10601);
WREG32(0x657C, 0x87A08AA0);
WREG32(0x6578, 0x10602);
WREG32(0x657C, 0x8010BE98);
WREG32(0x6578, 0x10700);
WREG32(0x657C, 0xBF10BFF0);
WREG32(0x6578, 0x10701);
WREG32(0x657C, 0x886089E0);
WREG32(0x6578, 0x10702);
WREG32(0x657C, 0x8018BEB0);
WREG32(0x6578, 0x10800);
WREG32(0x657C, 0xBED8BFE8);
WREG32(0x6578, 0x10801);
WREG32(0x657C, 0x89408940);
WREG32(0x6578, 0x10802);
WREG32(0x657C, 0xBFE8BED8);
WREG32(0x6578, 0x20000);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20001);
WREG32(0x657C, 0x90008000);
WREG32(0x6578, 0x20002);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20003);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20100);
WREG32(0x657C, 0x80108000);
WREG32(0x6578, 0x20101);
WREG32(0x657C, 0x8FE0BF70);
WREG32(0x6578, 0x20102);
WREG32(0x657C, 0xBFE880C0);
WREG32(0x6578, 0x20103);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20200);
WREG32(0x657C, 0x8018BFF8);
WREG32(0x6578, 0x20201);
WREG32(0x657C, 0x8F80BF08);
WREG32(0x6578, 0x20202);
WREG32(0x657C, 0xBFD081A0);
WREG32(0x6578, 0x20203);
WREG32(0x657C, 0xBFF88000);
WREG32(0x6578, 0x20300);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20301);
WREG32(0x657C, 0x8EE0BEC0);
WREG32(0x6578, 0x20302);
WREG32(0x657C, 0xBFB082A0);
WREG32(0x6578, 0x20303);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20400);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20401);
WREG32(0x657C, 0x8E00BEA0);
WREG32(0x6578, 0x20402);
WREG32(0x657C, 0xBF8883C0);
WREG32(0x6578, 0x20403);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20500);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20501);
WREG32(0x657C, 0x8D00BE90);
WREG32(0x6578, 0x20502);
WREG32(0x657C, 0xBF588500);
WREG32(0x6578, 0x20503);
WREG32(0x657C, 0x80008008);
WREG32(0x6578, 0x20600);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20601);
WREG32(0x657C, 0x8BC0BE98);
WREG32(0x6578, 0x20602);
WREG32(0x657C, 0xBF308660);
WREG32(0x6578, 0x20603);
WREG32(0x657C, 0x80008008);
WREG32(0x6578, 0x20700);
WREG32(0x657C, 0x80108000);
WREG32(0x6578, 0x20701);
WREG32(0x657C, 0x8A80BEB0);
WREG32(0x6578, 0x20702);
WREG32(0x657C, 0xBF0087C0);
WREG32(0x6578, 0x20703);
WREG32(0x657C, 0x80008008);
WREG32(0x6578, 0x20800);
WREG32(0x657C, 0x80108000);
WREG32(0x6578, 0x20801);
WREG32(0x657C, 0x8920BED0);
WREG32(0x6578, 0x20802);
WREG32(0x657C, 0xBED08920);
WREG32(0x6578, 0x20803);
WREG32(0x657C, 0x80008010);
WREG32(0x6578, 0x30000);
WREG32(0x657C, 0x90008000);
WREG32(0x6578, 0x30001);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x30100);
WREG32(0x657C, 0x8FE0BF90);
WREG32(0x6578, 0x30101);
WREG32(0x657C, 0xBFF880A0);
WREG32(0x6578, 0x30200);
WREG32(0x657C, 0x8F60BF40);
WREG32(0x6578, 0x30201);
WREG32(0x657C, 0xBFE88180);
WREG32(0x6578, 0x30300);
WREG32(0x657C, 0x8EC0BF00);
WREG32(0x6578, 0x30301);
WREG32(0x657C, 0xBFC88280);
WREG32(0x6578, 0x30400);
WREG32(0x657C, 0x8DE0BEE0);
WREG32(0x6578, 0x30401);
WREG32(0x657C, 0xBFA083A0);
WREG32(0x6578, 0x30500);
WREG32(0x657C, 0x8CE0BED0);
WREG32(0x6578, 0x30501);
WREG32(0x657C, 0xBF7884E0);
WREG32(0x6578, 0x30600);
WREG32(0x657C, 0x8BA0BED8);
WREG32(0x6578, 0x30601);
WREG32(0x657C, 0xBF508640);
WREG32(0x6578, 0x30700);
WREG32(0x657C, 0x8A60BEE8);
WREG32(0x6578, 0x30701);
WREG32(0x657C, 0xBF2087A0);
WREG32(0x6578, 0x30800);
WREG32(0x657C, 0x8900BF00);
WREG32(0x6578, 0x30801);
WREG32(0x657C, 0xBF008900);
}
static void static void
atombios_yuv_setup(struct drm_encoder *encoder, bool enable) atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
{ {
...@@ -1073,129 +842,6 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable) ...@@ -1073,129 +842,6 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
WREG32(reg, temp); WREG32(reg, temp);
} }
static void
atombios_overscan_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
SET_CRTC_OVERSCAN_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
memset(&args, 0, sizeof(args));
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
args.ucCRTC = radeon_crtc->crtc_id;
if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type == RMX_FULL) {
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
} else if (radeon_encoder->rmx_type == RMX_CENTER) {
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
} else if (radeon_encoder->rmx_type == RMX_ASPECT) {
int a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
int a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
if (a1 > a2) {
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
} else if (a2 > a1) {
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
}
}
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
static void
atombios_scaler_setup(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
/* fixme - fill in enc_priv for atom dac */
enum radeon_tv_std tv_std = TV_STD_NTSC;
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
return;
memset(&args, 0, sizeof(args));
args.ucScaler = radeon_crtc->crtc_id;
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
switch (tv_std) {
case TV_STD_NTSC:
default:
args.ucTVStandard = ATOM_TV_NTSC;
break;
case TV_STD_PAL:
args.ucTVStandard = ATOM_TV_PAL;
break;
case TV_STD_PAL_M:
args.ucTVStandard = ATOM_TV_PALM;
break;
case TV_STD_PAL_60:
args.ucTVStandard = ATOM_TV_PAL60;
break;
case TV_STD_NTSC_J:
args.ucTVStandard = ATOM_TV_NTSCJ;
break;
case TV_STD_SCART_PAL:
args.ucTVStandard = ATOM_TV_PAL; /* ??? */
break;
case TV_STD_SECAM:
args.ucTVStandard = ATOM_TV_SECAM;
break;
case TV_STD_PAL_CN:
args.ucTVStandard = ATOM_TV_PALCN;
break;
}
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) {
args.ucTVStandard = ATOM_TV_CV;
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type == RMX_FULL)
args.ucEnable = ATOM_SCALER_EXPANSION;
else if (radeon_encoder->rmx_type == RMX_CENTER)
args.ucEnable = ATOM_SCALER_CENTER;
else if (radeon_encoder->rmx_type == RMX_ASPECT)
args.ucEnable = ATOM_SCALER_EXPANSION;
} else {
if (ASIC_IS_AVIVO(rdev))
args.ucEnable = ATOM_SCALER_DISABLE;
else
args.ucEnable = ATOM_SCALER_CENTER;
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
atom_rv515_force_tv_scaler(rdev);
}
}
static void static void
radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
{ {
...@@ -1448,8 +1094,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, ...@@ -1448,8 +1094,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
radeon_encoder->pixel_clock = adjusted_mode->clock; radeon_encoder->pixel_clock = adjusted_mode->clock;
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
atombios_overscan_setup(encoder, mode, adjusted_mode);
atombios_scaler_setup(encoder);
atombios_set_encoder_crtc_source(encoder); atombios_set_encoder_crtc_source(encoder);
if (ASIC_IS_AVIVO(rdev)) { if (ASIC_IS_AVIVO(rdev)) {
...@@ -1667,6 +1311,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su ...@@ -1667,6 +1311,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
radeon_encoder->encoder_id = encoder_id; radeon_encoder->encoder_id = encoder_id;
radeon_encoder->devices = supported_device; radeon_encoder->devices = supported_device;
radeon_encoder->rmx_type = RMX_OFF;
switch (radeon_encoder->encoder_id) { switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_LVDS: case ENCODER_OBJECT_ID_INTERNAL_LVDS:
......
...@@ -101,9 +101,10 @@ static int radeonfb_setcolreg(unsigned regno, ...@@ -101,9 +101,10 @@ static int radeonfb_setcolreg(unsigned regno,
break; break;
case 24: case 24:
case 32: case 32:
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | fb->pseudo_palette[regno] =
(green & 0xff00) | (((red >> 8) & 0xff) << info->var.red.offset) |
((blue & 0xff00) >> 8); (((green >> 8) & 0xff) << info->var.green.offset) |
(((blue >> 8) & 0xff) << info->var.blue.offset);
break; break;
} }
} }
...@@ -154,6 +155,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var, ...@@ -154,6 +155,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
var->transp.length = 0; var->transp.length = 0;
var->transp.offset = 0; var->transp.offset = 0;
break; break;
#ifdef __LITTLE_ENDIAN
case 15: case 15:
var->red.offset = 10; var->red.offset = 10;
var->green.offset = 5; var->green.offset = 5;
...@@ -194,6 +196,28 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var, ...@@ -194,6 +196,28 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
var->transp.length = 8; var->transp.length = 8;
var->transp.offset = 24; var->transp.offset = 24;
break; break;
#else
case 24:
var->red.offset = 8;
var->green.offset = 16;
var->blue.offset = 24;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 0;
var->transp.offset = 0;
break;
case 32:
var->red.offset = 8;
var->green.offset = 16;
var->blue.offset = 24;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 8;
var->transp.offset = 0;
break;
#endif
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -447,10 +471,10 @@ static struct notifier_block paniced = { ...@@ -447,10 +471,10 @@ static struct notifier_block paniced = {
.notifier_call = radeonfb_panic, .notifier_call = radeonfb_panic,
}; };
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
{ {
int aligned = width; int aligned = width;
int align_large = (ASIC_IS_AVIVO(rdev)); int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
int pitch_mask = 0; int pitch_mask = 0;
switch (bpp / 8) { switch (bpp / 8) {
...@@ -488,12 +512,13 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -488,12 +512,13 @@ int radeonfb_create(struct radeon_device *rdev,
u64 fb_gpuaddr; u64 fb_gpuaddr;
void *fbptr = NULL; void *fbptr = NULL;
unsigned long tmp; unsigned long tmp;
bool fb_tiled = false; /* useful for testing */
mode_cmd.width = surface_width; mode_cmd.width = surface_width;
mode_cmd.height = surface_height; mode_cmd.height = surface_height;
mode_cmd.bpp = 32; mode_cmd.bpp = 32;
/* need to align pitch with crtc limits */ /* need to align pitch with crtc limits */
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
mode_cmd.depth = 24; mode_cmd.depth = 24;
size = mode_cmd.pitch * mode_cmd.height; size = mode_cmd.pitch * mode_cmd.height;
...@@ -511,6 +536,8 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -511,6 +536,8 @@ int radeonfb_create(struct radeon_device *rdev,
} }
robj = gobj->driver_private; robj = gobj->driver_private;
if (fb_tiled)
radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
mutex_lock(&rdev->ddev->struct_mutex); mutex_lock(&rdev->ddev->struct_mutex);
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
if (fb == NULL) { if (fb == NULL) {
...@@ -539,6 +566,9 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -539,6 +566,9 @@ int radeonfb_create(struct radeon_device *rdev,
} }
rfbdev = info->par; rfbdev = info->par;
if (fb_tiled)
radeon_object_check_tiling(robj, 0, 0);
ret = radeon_object_kmap(robj, &fbptr); ret = radeon_object_kmap(robj, &fbptr);
if (ret) { if (ret) {
goto out_unref; goto out_unref;
...@@ -572,6 +602,11 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -572,6 +602,11 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.width = -1; info->var.width = -1;
info->var.xres = fb_width; info->var.xres = fb_width;
info->var.yres = fb_height; info->var.yres = fb_height;
/* setup aperture base/size for vesafb takeover */
info->aperture_base = rdev->ddev->mode_config.fb_base;
info->aperture_size = rdev->mc.real_vram_size;
info->fix.mmio_start = 0; info->fix.mmio_start = 0;
info->fix.mmio_len = 0; info->fix.mmio_len = 0;
info->pixmap.size = 64*1024; info->pixmap.size = 64*1024;
...@@ -600,6 +635,7 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -600,6 +635,7 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.transp.offset = 0; info->var.transp.offset = 0;
info->var.transp.length = 0; info->var.transp.length = 0;
break; break;
#ifdef __LITTLE_ENDIAN
case 15: case 15:
info->var.red.offset = 10; info->var.red.offset = 10;
info->var.green.offset = 5; info->var.green.offset = 5;
...@@ -639,7 +675,29 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -639,7 +675,29 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.transp.offset = 24; info->var.transp.offset = 24;
info->var.transp.length = 8; info->var.transp.length = 8;
break; break;
#else
case 24:
info->var.red.offset = 8;
info->var.green.offset = 16;
info->var.blue.offset = 24;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 0;
break;
case 32:
info->var.red.offset = 8;
info->var.green.offset = 16;
info->var.blue.offset = 24;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 8;
break;
default: default:
#endif
break; break;
} }
......
...@@ -195,7 +195,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible) ...@@ -195,7 +195,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
r = wait_event_interruptible_timeout(rdev->fence_drv.queue, r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
radeon_fence_signaled(fence), timeout); radeon_fence_signaled(fence), timeout);
if (unlikely(r == -ERESTARTSYS)) { if (unlikely(r == -ERESTARTSYS)) {
return -ERESTART; return -EBUSY;
} }
} else { } else {
r = wait_event_timeout(rdev->fence_drv.queue, r = wait_event_timeout(rdev->fence_drv.queue,
......
...@@ -177,7 +177,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, ...@@ -177,7 +177,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
return -ENOMEM; return -ENOMEM;
} }
rdev->gart.pages[p] = pagelist[i]; rdev->gart.pages[p] = pagelist[i];
page_base = (uint32_t)rdev->gart.pages_addr[p]; page_base = rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) { for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
radeon_gart_set_page(rdev, t, page_base); radeon_gart_set_page(rdev, t, page_base);
page_base += 4096; page_base += 4096;
......
...@@ -157,9 +157,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, ...@@ -157,9 +157,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_info *args = data; struct drm_radeon_gem_info *args = data;
args->vram_size = rdev->mc.vram_size; args->vram_size = rdev->mc.real_vram_size;
/* FIXME: report somethings that makes sense */ /* FIXME: report somethings that makes sense */
args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024); args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
args->gart_size = rdev->mc.gtt_size; args->gart_size = rdev->mc.gtt_size;
return 0; return 0;
} }
...@@ -285,3 +285,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, ...@@ -285,3 +285,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return r; return r;
} }
int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
struct drm_radeon_gem_set_tiling *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
int r = 0;
DRM_DEBUG("%d \n", args->handle);
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL)
return -EINVAL;
robj = gobj->driver_private;
radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
return r;
}
int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
struct drm_radeon_gem_get_tiling *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
int r = 0;
DRM_DEBUG("\n");
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL)
return -EINVAL;
robj = gobj->driver_private;
radeon_object_get_tiling_flags(robj, &args->tiling_flags,
&args->pitch);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
return r;
}
...@@ -291,5 +291,7 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = { ...@@ -291,5 +291,7 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
}; };
int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
...@@ -30,170 +30,6 @@ ...@@ -30,170 +30,6 @@
#include "atom.h" #include "atom.h"
static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int xres = mode->hdisplay;
int yres = mode->vdisplay;
bool hscale = true, vscale = true;
int hsync_wid;
int vsync_wid;
int hsync_start;
uint32_t scale, inc;
uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active;
uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp;
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
DRM_DEBUG("\n");
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
(RADEON_VERT_STRETCH_RESERVED |
RADEON_VERT_AUTO_RATIO_INC);
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
(RADEON_HORZ_FP_LOOP_STRETCH |
RADEON_HORZ_AUTO_RATIO_INC);
crtc_more_cntl = 0;
if ((rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200)) {
/* This is to workaround the asic bug for RMX, some versions
of BIOS dosen't have this register initialized correctly. */
crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
}
fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
hsync_start = mode->crtc_hsync_start - 8;
fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0));
fp_horz_vert_active = 0;
if (native_mode->panel_xres == 0 ||
native_mode->panel_yres == 0) {
hscale = false;
vscale = false;
} else {
if (xres > native_mode->panel_xres)
xres = native_mode->panel_xres;
if (yres > native_mode->panel_yres)
yres = native_mode->panel_yres;
if (xres == native_mode->panel_xres)
hscale = false;
if (yres == native_mode->panel_yres)
vscale = false;
}
if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type != RMX_CENTER) {
if (!hscale)
fp_horz_stretch |= ((xres/8-1) << 16);
else {
inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
/ native_mode->panel_xres + 1;
fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
RADEON_HORZ_STRETCH_BLEND |
RADEON_HORZ_STRETCH_ENABLE |
((native_mode->panel_xres/8-1) << 16));
}
if (!vscale)
fp_vert_stretch |= ((yres-1) << 12);
else {
inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
/ native_mode->panel_yres + 1;
fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
RADEON_VERT_STRETCH_ENABLE |
RADEON_VERT_STRETCH_BLEND |
((native_mode->panel_yres-1) << 12));
}
} else if (radeon_encoder->rmx_type == RMX_CENTER) {
int blank_width;
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
RADEON_CRTC_AUTO_VERT_CENTER_EN);
blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
if (blank_width > 110)
blank_width = 110;
fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0)));
fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
(((native_mode->panel_xres / 8) & 0x1ff) << 16));
}
} else {
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
}
WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch);
WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch);
WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl);
WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active);
WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid);
WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid);
WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
}
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -287,9 +123,6 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, ...@@ -287,9 +123,6 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
...@@ -318,7 +151,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, ...@@ -318,7 +151,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev)) { if (ASIC_IS_R300(rdev)) {
if (radeon_encoder->flags & RADEON_USE_RMX) if (radeon_encoder->rmx_type != RMX_OFF)
lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
} else } else
lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
...@@ -350,8 +183,6 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -350,8 +183,6 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
drm_mode_set_crtcinfo(adjusted_mode, 0); drm_mode_set_crtcinfo(adjusted_mode, 0);
radeon_encoder->flags &= ~RADEON_USE_RMX;
if (radeon_encoder->rmx_type != RMX_OFF) if (radeon_encoder->rmx_type != RMX_OFF)
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
...@@ -455,9 +286,6 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, ...@@ -455,9 +286,6 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
...@@ -653,9 +481,6 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, ...@@ -653,9 +481,6 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
tmp &= 0xfffff; tmp &= 0xfffff;
if (rdev->family == CHIP_RV280) { if (rdev->family == CHIP_RV280) {
...@@ -711,7 +536,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, ...@@ -711,7 +536,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
if (radeon_encoder->flags & RADEON_USE_RMX) if (radeon_encoder->rmx_type != RMX_OFF)
fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
else else
fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
...@@ -820,9 +645,6 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, ...@@ -820,9 +645,6 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
if (rdev->is_atom_bios) { if (rdev->is_atom_bios) {
radeon_encoder->pixel_clock = adjusted_mode->clock; radeon_encoder->pixel_clock = adjusted_mode->clock;
atombios_external_tmds_setup(encoder, ATOM_ENABLE); atombios_external_tmds_setup(encoder, ATOM_ENABLE);
...@@ -856,7 +678,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, ...@@ -856,7 +678,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
if (radeon_encoder->flags & RADEON_USE_RMX) if (radeon_encoder->rmx_type != RMX_OFF)
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
else else
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
...@@ -1014,9 +836,6 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, ...@@ -1014,9 +836,6 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
if (rdev->family != CHIP_R200) { if (rdev->family != CHIP_R200) {
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
if (rdev->family == CHIP_R420 || if (rdev->family == CHIP_R420 ||
...@@ -1243,6 +1062,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t ...@@ -1243,6 +1062,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
radeon_encoder->encoder_id = encoder_id; radeon_encoder->encoder_id = encoder_id;
radeon_encoder->devices = supported_device; radeon_encoder->devices = supported_device;
radeon_encoder->rmx_type = RMX_OFF;
switch (radeon_encoder->encoder_id) { switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_LVDS: case ENCODER_OBJECT_ID_INTERNAL_LVDS:
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h> #include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include "radeon_fixed.h"
struct radeon_device;
#define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base) #define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base)
#define to_radeon_connector(x) container_of(x, struct radeon_connector, base) #define to_radeon_connector(x) container_of(x, struct radeon_connector, base)
...@@ -124,6 +127,7 @@ struct radeon_tmds_pll { ...@@ -124,6 +127,7 @@ struct radeon_tmds_pll {
#define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) #define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8)
#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
#define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10)
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
struct radeon_pll { struct radeon_pll {
uint16_t reference_freq; uint16_t reference_freq;
...@@ -170,6 +174,18 @@ struct radeon_mode_info { ...@@ -170,6 +174,18 @@ struct radeon_mode_info {
struct atom_context *atom_context; struct atom_context *atom_context;
enum radeon_connector_table connector_table; enum radeon_connector_table connector_table;
bool mode_config_initialized; bool mode_config_initialized;
struct radeon_crtc *crtcs[2];
};
struct radeon_native_mode {
/* preferred mode */
uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t dotclock;
uint32_t flags;
}; };
struct radeon_crtc { struct radeon_crtc {
...@@ -185,19 +201,13 @@ struct radeon_crtc { ...@@ -185,19 +201,13 @@ struct radeon_crtc {
uint64_t cursor_addr; uint64_t cursor_addr;
int cursor_width; int cursor_width;
int cursor_height; int cursor_height;
}; uint32_t legacy_display_base_addr;
uint32_t legacy_cursor_offset;
#define RADEON_USE_RMX 1 enum radeon_rmx_type rmx_type;
uint32_t devices;
struct radeon_native_mode { fixed20_12 vsc;
/* preferred mode */ fixed20_12 hsc;
uint32_t panel_xres, panel_yres; struct radeon_native_mode native_mode;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t dotclock;
uint32_t flags;
}; };
struct radeon_encoder_primary_dac { struct radeon_encoder_primary_dac {
...@@ -383,16 +393,9 @@ void radeon_enc_destroy(struct drm_encoder *encoder); ...@@ -383,16 +393,9 @@ void radeon_enc_destroy(struct drm_encoder *encoder);
void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
void radeon_combios_asic_init(struct drm_device *dev); void radeon_combios_asic_init(struct drm_device *dev);
extern int radeon_static_clocks_init(struct drm_device *dev); extern int radeon_static_clocks_init(struct drm_device *dev);
void radeon_init_disp_bw_legacy(struct drm_device *dev, bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode1, struct drm_display_mode *mode,
uint32_t pixel_bytes1, struct drm_display_mode *adjusted_mode);
struct drm_display_mode *mode2, void atom_rv515_force_tv_scaler(struct radeon_device *rdev);
uint32_t pixel_bytes2);
void radeon_init_disp_bw_avivo(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2);
void radeon_init_disp_bandwidth(struct drm_device *dev);
#endif #endif
...@@ -44,6 +44,9 @@ struct radeon_object { ...@@ -44,6 +44,9 @@ struct radeon_object {
uint64_t gpu_addr; uint64_t gpu_addr;
void *kptr; void *kptr;
bool is_iomem; bool is_iomem;
uint32_t tiling_flags;
uint32_t pitch;
int surface_reg;
}; };
int radeon_ttm_init(struct radeon_device *rdev); int radeon_ttm_init(struct radeon_device *rdev);
...@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj) ...@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
robj = container_of(tobj, struct radeon_object, tobj); robj = container_of(tobj, struct radeon_object, tobj);
list_del_init(&robj->list); list_del_init(&robj->list);
radeon_object_clear_surface_reg(robj);
kfree(robj); kfree(robj);
} }
...@@ -99,16 +103,16 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain) ...@@ -99,16 +103,16 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
{ {
uint32_t flags = 0; uint32_t flags = 0;
if (domain & RADEON_GEM_DOMAIN_VRAM) { if (domain & RADEON_GEM_DOMAIN_VRAM) {
flags |= TTM_PL_FLAG_VRAM; flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
} }
if (domain & RADEON_GEM_DOMAIN_GTT) { if (domain & RADEON_GEM_DOMAIN_GTT) {
flags |= TTM_PL_FLAG_TT; flags |= TTM_PL_FLAG_TT | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
} }
if (domain & RADEON_GEM_DOMAIN_CPU) { if (domain & RADEON_GEM_DOMAIN_CPU) {
flags |= TTM_PL_FLAG_SYSTEM; flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
} }
if (!flags) { if (!flags) {
flags |= TTM_PL_FLAG_SYSTEM; flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
} }
return flags; return flags;
} }
...@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev, ...@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev,
} }
robj->rdev = rdev; robj->rdev = rdev;
robj->gobj = gobj; robj->gobj = gobj;
robj->surface_reg = -1;
INIT_LIST_HEAD(&robj->list); INIT_LIST_HEAD(&robj->list);
flags = radeon_object_flags_from_domain(domain); flags = radeon_object_flags_from_domain(domain);
...@@ -304,7 +309,7 @@ int radeon_object_wait(struct radeon_object *robj) ...@@ -304,7 +309,7 @@ int radeon_object_wait(struct radeon_object *robj)
} }
spin_lock(&robj->tobj.lock); spin_lock(&robj->tobj.lock);
if (robj->tobj.sync_obj) { if (robj->tobj.sync_obj) {
r = ttm_bo_wait(&robj->tobj, true, false, false); r = ttm_bo_wait(&robj->tobj, true, true, false);
} }
spin_unlock(&robj->tobj.lock); spin_unlock(&robj->tobj.lock);
radeon_object_unreserve(robj); radeon_object_unreserve(robj);
...@@ -403,7 +408,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence) ...@@ -403,7 +408,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
struct radeon_object *robj; struct radeon_object *robj;
struct radeon_fence *old_fence = NULL; struct radeon_fence *old_fence = NULL;
struct list_head *i; struct list_head *i;
uint32_t flags;
int r; int r;
r = radeon_object_list_reserve(head); r = radeon_object_list_reserve(head);
...@@ -414,27 +418,25 @@ int radeon_object_list_validate(struct list_head *head, void *fence) ...@@ -414,27 +418,25 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
list_for_each(i, head) { list_for_each(i, head) {
lobj = list_entry(i, struct radeon_object_list, list); lobj = list_entry(i, struct radeon_object_list, list);
robj = lobj->robj; robj = lobj->robj;
if (lobj->wdomain) {
flags = radeon_object_flags_from_domain(lobj->wdomain);
flags |= TTM_PL_FLAG_TT;
} else {
flags = radeon_object_flags_from_domain(lobj->rdomain);
flags |= TTM_PL_FLAG_TT;
flags |= TTM_PL_FLAG_VRAM;
}
if (!robj->pin_count) { if (!robj->pin_count) {
robj->tobj.proposed_placement = flags | TTM_PL_MASK_CACHING; if (lobj->wdomain) {
robj->tobj.proposed_placement =
radeon_object_flags_from_domain(lobj->wdomain);
} else {
robj->tobj.proposed_placement =
radeon_object_flags_from_domain(lobj->rdomain);
}
r = ttm_buffer_object_validate(&robj->tobj, r = ttm_buffer_object_validate(&robj->tobj,
robj->tobj.proposed_placement, robj->tobj.proposed_placement,
true, false); true, false);
if (unlikely(r)) { if (unlikely(r)) {
radeon_object_list_unreserve(head);
DRM_ERROR("radeon: failed to validate.\n"); DRM_ERROR("radeon: failed to validate.\n");
return r; return r;
} }
radeon_object_gpu_addr(robj); radeon_object_gpu_addr(robj);
} }
lobj->gpu_offset = robj->gpu_addr; lobj->gpu_offset = robj->gpu_addr;
lobj->tiling_flags = robj->tiling_flags;
if (fence) { if (fence) {
old_fence = (struct radeon_fence *)robj->tobj.sync_obj; old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
robj->tobj.sync_obj = radeon_fence_ref(fence); robj->tobj.sync_obj = radeon_fence_ref(fence);
...@@ -479,3 +481,127 @@ unsigned long radeon_object_size(struct radeon_object *robj) ...@@ -479,3 +481,127 @@ unsigned long radeon_object_size(struct radeon_object *robj)
{ {
return robj->tobj.num_pages << PAGE_SHIFT; return robj->tobj.num_pages << PAGE_SHIFT;
} }
int radeon_object_get_surface_reg(struct radeon_object *robj)
{
struct radeon_device *rdev = robj->rdev;
struct radeon_surface_reg *reg;
struct radeon_object *old_object;
int steal;
int i;
if (!robj->tiling_flags)
return 0;
if (robj->surface_reg >= 0) {
reg = &rdev->surface_regs[robj->surface_reg];
i = robj->surface_reg;
goto out;
}
steal = -1;
for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
reg = &rdev->surface_regs[i];
if (!reg->robj)
break;
old_object = reg->robj;
if (old_object->pin_count == 0)
steal = i;
}
/* if we are all out */
if (i == RADEON_GEM_MAX_SURFACES) {
if (steal == -1)
return -ENOMEM;
/* find someone with a surface reg and nuke their BO */
reg = &rdev->surface_regs[steal];
old_object = reg->robj;
/* blow away the mapping */
DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
ttm_bo_unmap_virtual(&old_object->tobj);
old_object->surface_reg = -1;
i = steal;
}
robj->surface_reg = i;
reg->robj = robj;
out:
radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
robj->tobj.mem.mm_node->start << PAGE_SHIFT,
robj->tobj.num_pages << PAGE_SHIFT);
return 0;
}
void radeon_object_clear_surface_reg(struct radeon_object *robj)
{
struct radeon_device *rdev = robj->rdev;
struct radeon_surface_reg *reg;
if (robj->surface_reg == -1)
return;
reg = &rdev->surface_regs[robj->surface_reg];
radeon_clear_surface_reg(rdev, robj->surface_reg);
reg->robj = NULL;
robj->surface_reg = -1;
}
void radeon_object_set_tiling_flags(struct radeon_object *robj,
uint32_t tiling_flags, uint32_t pitch)
{
robj->tiling_flags = tiling_flags;
robj->pitch = pitch;
}
void radeon_object_get_tiling_flags(struct radeon_object *robj,
uint32_t *tiling_flags,
uint32_t *pitch)
{
if (tiling_flags)
*tiling_flags = robj->tiling_flags;
if (pitch)
*pitch = robj->pitch;
}
int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
bool force_drop)
{
if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
return 0;
if (force_drop) {
radeon_object_clear_surface_reg(robj);
return 0;
}
if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
if (!has_moved)
return 0;
if (robj->surface_reg >= 0)
radeon_object_clear_surface_reg(robj);
return 0;
}
if ((robj->surface_reg >= 0) && !has_moved)
return 0;
return radeon_object_get_surface_reg(robj);
}
void radeon_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem)
{
struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
radeon_object_check_tiling(robj, 0, 1);
}
void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
{
struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
radeon_object_check_tiling(robj, 0, 0);
}
...@@ -126,32 +126,19 @@ static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -126,32 +126,19 @@ static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
} }
} }
static void radeon_ib_cpu_flush(struct radeon_device *rdev,
struct radeon_ib *ib)
{
unsigned long tmp;
unsigned i;
/* To force CPU cache flush ugly but seems reliable */
for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) {
tmp = readl(&ib->ptr[i]);
}
}
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
{ {
int r = 0; int r = 0;
mutex_lock(&rdev->ib_pool.mutex); mutex_lock(&rdev->ib_pool.mutex);
radeon_ib_align(rdev, ib); radeon_ib_align(rdev, ib);
radeon_ib_cpu_flush(rdev, ib);
if (!ib->length_dw || !rdev->cp.ready) { if (!ib->length_dw || !rdev->cp.ready) {
/* TODO: Nothings in the ib we should report. */ /* TODO: Nothings in the ib we should report. */
mutex_unlock(&rdev->ib_pool.mutex); mutex_unlock(&rdev->ib_pool.mutex);
DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
return -EINVAL; return -EINVAL;
} }
/* 64 dwords should be enought for fence too */ /* 64 dwords should be enough for fence too */
r = radeon_ring_lock(rdev, 64); r = radeon_ring_lock(rdev, 64);
if (r) { if (r) {
DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
......
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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: Dave Airlie
* Alex Deucher
* Jerome Glisse
*/
#ifndef __RADEON_SHARE_H__
#define __RADEON_SHARE_H__
void r100_vram_init_sizes(struct radeon_device *rdev);
void rs690_line_buffer_adjust(struct radeon_device *rdev,
struct drm_display_mode *mode1,
struct drm_display_mode *mode2);
void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
#endif
/*
* Copyright 2009 VMware, 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: Michel Dänzer
*/
#include <drm/drmP.h>
#include <drm/radeon_drm.h>
#include "radeon_reg.h"
#include "radeon.h"
/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
void radeon_test_moves(struct radeon_device *rdev)
{
struct radeon_object *vram_obj = NULL;
struct radeon_object **gtt_obj = NULL;
struct radeon_fence *fence = NULL;
uint64_t gtt_addr, vram_addr;
unsigned i, n, size;
int r;
size = 1024 * 1024;
/* Number of tests =
* (Total GTT - IB pool - writeback page - ring buffer) / test size
*/
n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - 4096 -
rdev->cp.ring_size) / size;
gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
if (!gtt_obj) {
DRM_ERROR("Failed to allocate %d pointers\n", n);
r = 1;
goto out_cleanup;
}
r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
false, &vram_obj);
if (r) {
DRM_ERROR("Failed to create VRAM object\n");
goto out_cleanup;
}
r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
if (r) {
DRM_ERROR("Failed to pin VRAM object\n");
goto out_cleanup;
}
for (i = 0; i < n; i++) {
void *gtt_map, *vram_map;
void **gtt_start, **gtt_end;
void **vram_start, **vram_end;
r = radeon_object_create(rdev, NULL, size, true,
RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i);
if (r) {
DRM_ERROR("Failed to create GTT object %d\n", i);
goto out_cleanup;
}
r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
if (r) {
DRM_ERROR("Failed to pin GTT object %d\n", i);
goto out_cleanup;
}
r = radeon_object_kmap(gtt_obj[i], &gtt_map);
if (r) {
DRM_ERROR("Failed to map GTT object %d\n", i);
goto out_cleanup;
}
for (gtt_start = gtt_map, gtt_end = gtt_map + size;
gtt_start < gtt_end;
gtt_start++)
*gtt_start = gtt_start;
radeon_object_kunmap(gtt_obj[i]);
r = radeon_fence_create(rdev, &fence);
if (r) {
DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i);
goto out_cleanup;
}
r = radeon_copy(rdev, gtt_addr, vram_addr, size / 4096, fence);
if (r) {
DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
goto out_cleanup;
}
r = radeon_fence_wait(fence, false);
if (r) {
DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
goto out_cleanup;
}
radeon_fence_unref(&fence);
r = radeon_object_kmap(vram_obj, &vram_map);
if (r) {
DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
goto out_cleanup;
}
for (gtt_start = gtt_map, gtt_end = gtt_map + size,
vram_start = vram_map, vram_end = vram_map + size;
vram_start < vram_end;
gtt_start++, vram_start++) {
if (*vram_start != gtt_start) {
DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
"expected 0x%p (GTT map 0x%p-0x%p)\n",
i, *vram_start, gtt_start, gtt_map,
gtt_end);
radeon_object_kunmap(vram_obj);
goto out_cleanup;
}
*vram_start = vram_start;
}
radeon_object_kunmap(vram_obj);
r = radeon_fence_create(rdev, &fence);
if (r) {
DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i);
goto out_cleanup;
}
r = radeon_copy(rdev, vram_addr, gtt_addr, size / 4096, fence);
if (r) {
DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
goto out_cleanup;
}
r = radeon_fence_wait(fence, false);
if (r) {
DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
goto out_cleanup;
}
radeon_fence_unref(&fence);
r = radeon_object_kmap(gtt_obj[i], &gtt_map);
if (r) {
DRM_ERROR("Failed to map GTT object after copy %d\n", i);
goto out_cleanup;
}
for (gtt_start = gtt_map, gtt_end = gtt_map + size,
vram_start = vram_map, vram_end = vram_map + size;
gtt_start < gtt_end;
gtt_start++, vram_start++) {
if (*gtt_start != vram_start) {
DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
"expected 0x%p (VRAM map 0x%p-0x%p)\n",
i, *gtt_start, vram_start, vram_map,
vram_end);
radeon_object_kunmap(gtt_obj[i]);
goto out_cleanup;
}
}
radeon_object_kunmap(gtt_obj[i]);
DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
gtt_addr - rdev->mc.gtt_location);
}
out_cleanup:
if (vram_obj) {
radeon_object_unpin(vram_obj);
radeon_object_unref(&vram_obj);
}
if (gtt_obj) {
for (i = 0; i < n; i++) {
if (gtt_obj[i]) {
radeon_object_unpin(gtt_obj[i]);
radeon_object_unref(&gtt_obj[i]);
}
}
kfree(gtt_obj);
}
if (fence) {
radeon_fence_unref(&fence);
}
if (r) {
printk(KERN_WARNING "Error while testing BO move.\n");
}
}
...@@ -355,23 +355,26 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, ...@@ -355,23 +355,26 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
if (!rdev->cp.ready) { if (!rdev->cp.ready) {
/* use memcpy */ /* use memcpy */
DRM_ERROR("CP is not ready use memcpy.\n"); DRM_ERROR("CP is not ready use memcpy.\n");
return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); goto memcpy;
} }
if (old_mem->mem_type == TTM_PL_VRAM && if (old_mem->mem_type == TTM_PL_VRAM &&
new_mem->mem_type == TTM_PL_SYSTEM) { new_mem->mem_type == TTM_PL_SYSTEM) {
return radeon_move_vram_ram(bo, evict, interruptible, r = radeon_move_vram_ram(bo, evict, interruptible,
no_wait, new_mem); no_wait, new_mem);
} else if (old_mem->mem_type == TTM_PL_SYSTEM && } else if (old_mem->mem_type == TTM_PL_SYSTEM &&
new_mem->mem_type == TTM_PL_VRAM) { new_mem->mem_type == TTM_PL_VRAM) {
return radeon_move_ram_vram(bo, evict, interruptible, r = radeon_move_ram_vram(bo, evict, interruptible,
no_wait, new_mem); no_wait, new_mem);
} else { } else {
r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem); r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem);
if (unlikely(r)) {
return r;
}
} }
if (r) {
memcpy:
r = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
}
return r; return r;
} }
...@@ -429,6 +432,8 @@ static struct ttm_bo_driver radeon_bo_driver = { ...@@ -429,6 +432,8 @@ static struct ttm_bo_driver radeon_bo_driver = {
.sync_obj_flush = &radeon_sync_obj_flush, .sync_obj_flush = &radeon_sync_obj_flush,
.sync_obj_unref = &radeon_sync_obj_unref, .sync_obj_unref = &radeon_sync_obj_unref,
.sync_obj_ref = &radeon_sync_obj_ref, .sync_obj_ref = &radeon_sync_obj_ref,
.move_notify = &radeon_bo_move_notify,
.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
}; };
int radeon_ttm_init(struct radeon_device *rdev) int radeon_ttm_init(struct radeon_device *rdev)
...@@ -442,13 +447,14 @@ int radeon_ttm_init(struct radeon_device *rdev) ...@@ -442,13 +447,14 @@ int radeon_ttm_init(struct radeon_device *rdev)
/* No others user of address space so set it to 0 */ /* No others user of address space so set it to 0 */
r = ttm_bo_device_init(&rdev->mman.bdev, r = ttm_bo_device_init(&rdev->mman.bdev,
rdev->mman.mem_global_ref.object, rdev->mman.mem_global_ref.object,
&radeon_bo_driver, DRM_FILE_PAGE_OFFSET); &radeon_bo_driver, DRM_FILE_PAGE_OFFSET,
rdev->need_dma32);
if (r) { if (r) {
DRM_ERROR("failed initializing buffer object driver(%d).\n", r); DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
return r; return r;
} }
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0, r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0,
((rdev->mc.aper_size) >> PAGE_SHIFT)); ((rdev->mc.real_vram_size) >> PAGE_SHIFT));
if (r) { if (r) {
DRM_ERROR("Failed initializing VRAM heap.\n"); DRM_ERROR("Failed initializing VRAM heap.\n");
return r; return r;
...@@ -465,7 +471,7 @@ int radeon_ttm_init(struct radeon_device *rdev) ...@@ -465,7 +471,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
return r; return r;
} }
DRM_INFO("radeon: %uM of VRAM memory ready\n", DRM_INFO("radeon: %uM of VRAM memory ready\n",
rdev->mc.vram_size / (1024 * 1024)); rdev->mc.real_vram_size / (1024 * 1024));
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0, r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
((rdev->mc.gtt_size) >> PAGE_SHIFT)); ((rdev->mc.gtt_size) >> PAGE_SHIFT));
if (r) { if (r) {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "radeon_share.h"
/* rs400,rs480 depends on : */ /* rs400,rs480 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); void r100_hdp_reset(struct radeon_device *rdev);
...@@ -164,7 +165,9 @@ int rs400_gart_enable(struct radeon_device *rdev) ...@@ -164,7 +165,9 @@ int rs400_gart_enable(struct radeon_device *rdev)
WREG32(RADEON_BUS_CNTL, tmp); WREG32(RADEON_BUS_CNTL, tmp);
} }
/* Table should be in 32bits address space so ignore bits above. */ /* Table should be in 32bits address space so ignore bits above. */
tmp = rdev->gart.table_addr & 0xfffff000; tmp = (u32)rdev->gart.table_addr & 0xfffff000;
tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4;
WREG32_MC(RS480_GART_BASE, tmp); WREG32_MC(RS480_GART_BASE, tmp);
/* TODO: more tweaking here */ /* TODO: more tweaking here */
WREG32_MC(RS480_GART_FEATURE_ID, WREG32_MC(RS480_GART_FEATURE_ID,
...@@ -201,10 +204,17 @@ void rs400_gart_disable(struct radeon_device *rdev) ...@@ -201,10 +204,17 @@ void rs400_gart_disable(struct radeon_device *rdev)
int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{ {
uint32_t entry;
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
} }
rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC);
entry = (lower_32_bits(addr) & PAGE_MASK) |
((upper_32_bits(addr) & 0xff) << 4) |
0xc;
entry = cpu_to_le32(entry);
rdev->gart.table.ram.ptr[i] = entry;
return 0; return 0;
} }
...@@ -223,10 +233,9 @@ int rs400_mc_init(struct radeon_device *rdev) ...@@ -223,10 +233,9 @@ int rs400_mc_init(struct radeon_device *rdev)
rs400_gpu_init(rdev); rs400_gpu_init(rdev);
rs400_gart_disable(rdev); rs400_gart_disable(rdev);
rdev->mc.gtt_location = rdev->mc.vram_size; rdev->mc.gtt_location = rdev->mc.mc_vram_size;
rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
rdev->mc.vram_location = 0xFFFFFFFFUL;
r = radeon_mc_setup(rdev); r = radeon_mc_setup(rdev);
if (r) { if (r) {
return r; return r;
...@@ -238,7 +247,7 @@ int rs400_mc_init(struct radeon_device *rdev) ...@@ -238,7 +247,7 @@ int rs400_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32(RADEON_MC_FB_LOCATION, tmp); WREG32(RADEON_MC_FB_LOCATION, tmp);
...@@ -284,21 +293,12 @@ void rs400_gpu_init(struct radeon_device *rdev) ...@@ -284,21 +293,12 @@ void rs400_gpu_init(struct radeon_device *rdev)
*/ */
void rs400_vram_info(struct radeon_device *rdev) void rs400_vram_info(struct radeon_device *rdev)
{ {
uint32_t tom;
rs400_gart_adjust_size(rdev); rs400_gart_adjust_size(rdev);
/* DDR for all card after R300 & IGP */ /* DDR for all card after R300 & IGP */
rdev->mc.vram_is_ddr = true; rdev->mc.vram_is_ddr = true;
rdev->mc.vram_width = 128; rdev->mc.vram_width = 128;
/* read NB_TOM to get the amount of ram stolen for the GPU */ r100_vram_init_sizes(rdev);
tom = RREG32(RADEON_NB_TOM);
rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
/* Could aper size report 0 ? */
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
} }
......
...@@ -223,7 +223,7 @@ int rs600_mc_init(struct radeon_device *rdev) ...@@ -223,7 +223,7 @@ int rs600_mc_init(struct radeon_device *rdev)
printk(KERN_WARNING "Failed to wait MC idle while " printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16); tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16); tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(RS600_MC_FB_LOCATION, tmp); WREG32_MC(RS600_MC_FB_LOCATION, tmp);
...@@ -301,6 +301,11 @@ void rs600_vram_info(struct radeon_device *rdev) ...@@ -301,6 +301,11 @@ void rs600_vram_info(struct radeon_device *rdev)
rdev->mc.vram_width = 128; rdev->mc.vram_width = 128;
} }
void rs600_bandwidth_update(struct radeon_device *rdev)
{
/* FIXME: implement, should this be like rs690 ? */
}
/* /*
* Indirect registers accessor * Indirect registers accessor
......
此差异已折叠。
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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: Dave Airlie
* Alex Deucher
* Jerome Glisse
*/
#ifndef RS690R_H
#define RS690R_H
/* RS690/RS740 registers */
#define MC_INDEX 0x0078
# define MC_INDEX_MASK 0x1FF
# define MC_INDEX_WR_EN (1 << 9)
# define MC_INDEX_WR_ACK 0x7F
#define MC_DATA 0x007C
#define HDP_FB_LOCATION 0x0134
#define DC_LB_MEMORY_SPLIT 0x6520
#define DC_LB_MEMORY_SPLIT_MASK 0x00000003
#define DC_LB_MEMORY_SPLIT_SHIFT 0
#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0
#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1
#define DC_LB_MEMORY_SPLIT_D1_ONLY 2
#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3
#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
#define DC_LB_DISP1_END_ADR_SHIFT 4
#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0
#define D1MODE_PRIORITY_A_CNT 0x6548
#define MODE_PRIORITY_MARK_MASK 0x00007FFF
#define MODE_PRIORITY_OFF (1 << 16)
#define MODE_PRIORITY_ALWAYS_ON (1 << 20)
#define MODE_PRIORITY_FORCE_MASK (1 << 24)
#define D1MODE_PRIORITY_B_CNT 0x654C
#define LB_MAX_REQ_OUTSTANDING 0x6D58
#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F
#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0
#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000
#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16
#define DCP_CONTROL 0x6C9C
#define D2MODE_PRIORITY_A_CNT 0x6D48
#define D2MODE_PRIORITY_B_CNT 0x6D4C
/* MC indirect registers */
#define MC_STATUS_IDLE (1 << 0)
#define MC_MISC_CNTL 0x18
#define DISABLE_GTW (1 << 1)
#define GART_INDEX_REG_EN (1 << 12)
#define BLOCK_GFX_D3_EN (1 << 14)
#define GART_FEATURE_ID 0x2B
#define HANG_EN (1 << 11)
#define TLB_ENABLE (1 << 18)
#define P2P_ENABLE (1 << 19)
#define GTW_LAC_EN (1 << 25)
#define LEVEL2_GART (0 << 30)
#define LEVEL1_GART (1 << 30)
#define PDC_EN (1 << 31)
#define GART_BASE 0x2C
#define GART_CACHE_CNTRL 0x2E
# define GART_CACHE_INVALIDATE (1 << 0)
#define MC_STATUS 0x90
#define MCCFG_FB_LOCATION 0x100
#define MC_FB_START_MASK 0x0000FFFF
#define MC_FB_START_SHIFT 0
#define MC_FB_TOP_MASK 0xFFFF0000
#define MC_FB_TOP_SHIFT 16
#define MCCFG_AGP_LOCATION 0x101
#define MC_AGP_START_MASK 0x0000FFFF
#define MC_AGP_START_SHIFT 0
#define MC_AGP_TOP_MASK 0xFFFF0000
#define MC_AGP_TOP_SHIFT 16
#define MCCFG_AGP_BASE 0x102
#define MCCFG_AGP_BASE_2 0x103
#define MC_INIT_MISC_LAT_TIMER 0x104
#define MC_DISP0R_INIT_LAT_SHIFT 8
#define MC_DISP0R_INIT_LAT_MASK 0x00000F00
#define MC_DISP1R_INIT_LAT_SHIFT 12
#define MC_DISP1R_INIT_LAT_MASK 0x0000F000
#endif
此差异已折叠。
此差异已折叠。
...@@ -67,7 +67,7 @@ int rv770_mc_init(struct radeon_device *rdev) ...@@ -67,7 +67,7 @@ int rv770_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24); tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24);
tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24); tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24);
WREG32(R700_MC_VM_FB_LOCATION, tmp); WREG32(R700_MC_VM_FB_LOCATION, tmp);
......
此差异已折叠。
此差异已折叠。
...@@ -101,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -101,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
return VM_FAULT_NOPAGE; return VM_FAULT_NOPAGE;
} }
if (bdev->driver->fault_reserve_notify)
bdev->driver->fault_reserve_notify(bo);
/* /*
* Wait for buffer data in transit, due to a pipelined * Wait for buffer data in transit, due to a pipelined
* move. * move.
......
...@@ -86,10 +86,16 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages) ...@@ -86,10 +86,16 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages)
unsigned long i; unsigned long i;
for (i = 0; i < num_pages; ++i) { for (i = 0; i < num_pages; ++i) {
if (pages[i]) { struct page *page = pages[i];
unsigned long start = (unsigned long)page_address(pages[i]); void *page_virtual;
flush_dcache_range(start, start + PAGE_SIZE);
} if (unlikely(page == NULL))
continue;
page_virtual = kmap_atomic(page, KM_USER0);
flush_dcache_range((unsigned long) page_virtual,
(unsigned long) page_virtual + PAGE_SIZE);
kunmap_atomic(page_virtual, KM_USER0);
} }
#else #else
if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0) if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0)
...@@ -131,10 +137,17 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm) ...@@ -131,10 +137,17 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
static struct page *ttm_tt_alloc_page(unsigned page_flags) static struct page *ttm_tt_alloc_page(unsigned page_flags)
{ {
gfp_t gfp_flags = GFP_USER;
if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC)
return alloc_page(GFP_HIGHUSER | __GFP_ZERO); gfp_flags |= __GFP_ZERO;
if (page_flags & TTM_PAGE_FLAG_DMA32)
gfp_flags |= __GFP_DMA32;
else
gfp_flags |= __GFP_HIGHMEM;
return alloc_page(GFP_HIGHUSER); return alloc_page(gfp_flags);
} }
static void ttm_tt_free_user_pages(struct ttm_tt *ttm) static void ttm_tt_free_user_pages(struct ttm_tt *ttm)
......
此差异已折叠。
...@@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) ...@@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
/* check for s3c2440 i2c controller */
if (s3c24xx_i2c_is2440(i2c))
writel(0x0, i2c->regs + S3C2440_IICLC);
return 0; return 0;
} }
......
...@@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) ...@@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void)
platform_driver_unregister(&sh_mobile_i2c_driver); platform_driver_unregister(&sh_mobile_i2c_driver);
} }
module_init(sh_mobile_i2c_adap_init); subsys_initcall(sh_mobile_i2c_adap_init);
module_exit(sh_mobile_i2c_adap_exit); module_exit(sh_mobile_i2c_adap_exit);
MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
......
此差异已折叠。
此差异已折叠。
...@@ -1766,7 +1766,10 @@ int sdhci_add_host(struct sdhci_host *host) ...@@ -1766,7 +1766,10 @@ int sdhci_add_host(struct sdhci_host *host)
* Set host parameters. * Set host parameters.
*/ */
mmc->ops = &sdhci_ops; mmc->ops = &sdhci_ops;
mmc->f_min = host->max_clk / 256; if (host->ops->get_min_clock)
mmc->f_min = host->ops->get_min_clock(host);
else
mmc->f_min = host->max_clk / 256;
mmc->f_max = host->max_clk; mmc->f_max = host->max_clk;
mmc->caps = MMC_CAP_SDIO_IRQ; mmc->caps = MMC_CAP_SDIO_IRQ;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
obj-$(CONFIG_USB_SERIAL_ATEN2011) += aten2011.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册