Subversion Repositories Kolibri OS

Rev

Rev 3037 | Rev 3480 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2325 Serge 1
/*
2
 * Intel GTT (Graphics Translation Table) routines
3
 *
4
 * Caveat: This driver implements the linux agp interface, but this is far from
5
 * a agp driver! GTT support ended up here for purely historical reasons: The
6
 * old userspace intel graphics drivers needed an interface to map memory into
7
 * the GTT. And the drm provides a default interface for graphic devices sitting
8
 * on an agp port. So it made sense to fake the GTT support as an agp port to
9
 * avoid having to create a new api.
10
 *
11
 * With gem this does not make much sense anymore, just needlessly complicates
12
 * the code. But as long as the old graphics stack is still support, it's stuck
13
 * here.
14
 *
15
 * /fairy-tale-mode off
16
 */
17
 
18
#include 
19
#include 
20
#include 
21
#include 
3031 serge 22
#include 
3243 Serge 23
#include 
24
 
2325 Serge 25
//#include 
26
//#include 
27
//#include 
28
#include 
29
#include "agp.h"
30
#include "intel-agp.h"
3243 Serge 31
#include 
2325 Serge 32
 
33
#include 
34
 
35
struct pci_dev *
36
pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from);
37
 
38
 
39
#define PCI_VENDOR_ID_INTEL             0x8086
40
#define PCI_DEVICE_ID_INTEL_82830_HB    0x3575
41
#define PCI_DEVICE_ID_INTEL_82845G_HB   0x2560
2339 Serge 42
#define PCI_DEVICE_ID_INTEL_82915G_IG   0x2582
43
#define PCI_DEVICE_ID_INTEL_82915GM_IG  0x2592
44
#define PCI_DEVICE_ID_INTEL_82945G_IG   0x2772
45
#define PCI_DEVICE_ID_INTEL_82945GM_IG  0x27A2
2325 Serge 46
 
47
 
48
#define AGP_NORMAL_MEMORY 0
49
 
50
#define AGP_USER_TYPES (1 << 16)
51
#define AGP_USER_MEMORY (AGP_USER_TYPES)
52
#define AGP_USER_CACHED_MEMORY (AGP_USER_TYPES + 1)
53
 
54
 
55
 
56
/*
57
 * If we have Intel graphics, we're not going to have anything other than
58
 * an Intel IOMMU. So make the correct use of the PCI DMA API contingent
2339 Serge 59
 * on the Intel IOMMU support (CONFIG_INTEL_IOMMU).
2325 Serge 60
 * Only newer chipsets need to bother with this, of course.
61
 */
2339 Serge 62
#ifdef CONFIG_INTEL_IOMMU
2325 Serge 63
#define USE_PCI_DMA_API 1
64
#else
65
#define USE_PCI_DMA_API 0
66
#endif
67
 
68
struct intel_gtt_driver {
69
    unsigned int gen : 8;
70
    unsigned int is_g33 : 1;
71
    unsigned int is_pineview : 1;
72
    unsigned int is_ironlake : 1;
73
    unsigned int has_pgtbl_enable : 1;
74
    unsigned int dma_mask_size : 8;
75
    /* Chipset specific GTT setup */
76
    int (*setup)(void);
77
    /* This should undo anything done in ->setup() save the unmapping
78
     * of the mmio register file, that's done in the generic code. */
79
    void (*cleanup)(void);
80
    void (*write_entry)(dma_addr_t addr, unsigned int entry, unsigned int flags);
81
    /* Flags is a more or less chipset specific opaque value.
82
     * For chipsets that need to support old ums (non-gem) code, this
83
     * needs to be identical to the various supported agp memory types! */
84
    bool (*check_flags)(unsigned int flags);
85
    void (*chipset_flush)(void);
86
};
87
 
88
static struct _intel_private {
89
    struct intel_gtt base;
90
    const struct intel_gtt_driver *driver;
91
    struct pci_dev *pcidev; /* device one */
92
    struct pci_dev *bridge_dev;
93
    u8 __iomem *registers;
94
    phys_addr_t gtt_bus_addr;
95
    u32 PGETBL_save;
96
    u32 __iomem *gtt;       /* I915G */
97
    bool clear_fake_agp; /* on first access via agp, fill with scratch */
98
    int num_dcache_entries;
99
    void __iomem *i9xx_flush_page;
100
    char *i81x_gtt_table;
101
    struct resource ifp_resource;
102
    int resource_valid;
103
    struct page *scratch_page;
3031 serge 104
	int refcount;
2325 Serge 105
} intel_private;
106
 
107
#define INTEL_GTT_GEN   intel_private.driver->gen
108
#define IS_G33          intel_private.driver->is_g33
109
#define IS_PINEVIEW     intel_private.driver->is_pineview
110
#define IS_IRONLAKE     intel_private.driver->is_ironlake
111
#define HAS_PGTBL_EN    intel_private.driver->has_pgtbl_enable
112
 
113
static int intel_gtt_setup_scratch_page(void)
114
{
3243 Serge 115
	struct page *page;
3031 serge 116
	dma_addr_t dma_addr;
2325 Serge 117
 
3243 Serge 118
	page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
119
	if (page == NULL)
2325 Serge 120
        return -ENOMEM;
3243 Serge 121
    intel_private.base.scratch_page_dma = page_to_phys(page);
2325 Serge 122
 
3243 Serge 123
	intel_private.scratch_page = page;
2325 Serge 124
 
125
    return 0;
126
}
127
 
128
static unsigned int intel_gtt_stolen_size(void)
129
{
130
    u16 gmch_ctrl;
131
    u8 rdct;
132
    int local = 0;
133
    static const int ddt[4] = { 0, 16, 32, 64 };
134
    unsigned int stolen_size = 0;
135
 
136
    if (INTEL_GTT_GEN == 1)
137
        return 0; /* no stolen mem on i81x */
138
 
139
    pci_read_config_word(intel_private.bridge_dev,
140
                 I830_GMCH_CTRL, &gmch_ctrl);
141
 
142
    if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
143
        intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
144
        switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
145
        case I830_GMCH_GMS_STOLEN_512:
146
            stolen_size = KB(512);
147
            break;
148
        case I830_GMCH_GMS_STOLEN_1024:
149
            stolen_size = MB(1);
150
            break;
151
        case I830_GMCH_GMS_STOLEN_8192:
152
            stolen_size = MB(8);
153
            break;
154
        case I830_GMCH_GMS_LOCAL:
155
            rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
156
            stolen_size = (I830_RDRAM_ND(rdct) + 1) *
157
                    MB(ddt[I830_RDRAM_DDT(rdct)]);
158
            local = 1;
159
            break;
160
        default:
161
            stolen_size = 0;
162
            break;
163
        }
164
    } else {
165
        switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
166
        case I855_GMCH_GMS_STOLEN_1M:
167
            stolen_size = MB(1);
168
            break;
169
        case I855_GMCH_GMS_STOLEN_4M:
170
            stolen_size = MB(4);
171
            break;
172
        case I855_GMCH_GMS_STOLEN_8M:
173
            stolen_size = MB(8);
174
            break;
175
        case I855_GMCH_GMS_STOLEN_16M:
176
            stolen_size = MB(16);
177
            break;
178
        case I855_GMCH_GMS_STOLEN_32M:
179
            stolen_size = MB(32);
180
            break;
181
        case I915_GMCH_GMS_STOLEN_48M:
182
            stolen_size = MB(48);
183
            break;
184
        case I915_GMCH_GMS_STOLEN_64M:
185
            stolen_size = MB(64);
186
            break;
187
        case G33_GMCH_GMS_STOLEN_128M:
188
            stolen_size = MB(128);
189
            break;
190
        case G33_GMCH_GMS_STOLEN_256M:
191
            stolen_size = MB(256);
192
            break;
193
        case INTEL_GMCH_GMS_STOLEN_96M:
194
            stolen_size = MB(96);
195
            break;
196
        case INTEL_GMCH_GMS_STOLEN_160M:
197
            stolen_size = MB(160);
198
            break;
199
        case INTEL_GMCH_GMS_STOLEN_224M:
200
            stolen_size = MB(224);
201
            break;
202
        case INTEL_GMCH_GMS_STOLEN_352M:
203
            stolen_size = MB(352);
204
            break;
205
        default:
206
            stolen_size = 0;
207
            break;
208
        }
209
    }
210
 
211
    if (stolen_size > 0) {
2332 Serge 212
		dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n",
2325 Serge 213
               stolen_size / KB(1), local ? "local" : "stolen");
214
    } else {
2332 Serge 215
		dev_info(&intel_private.bridge_dev->dev,
216
		       "no pre-allocated video memory detected\n");
2325 Serge 217
        stolen_size = 0;
218
    }
219
 
220
    return stolen_size;
221
}
222
 
223
static void i965_adjust_pgetbl_size(unsigned int size_flag)
224
{
225
    u32 pgetbl_ctl, pgetbl_ctl2;
226
 
227
    /* ensure that ppgtt is disabled */
228
    pgetbl_ctl2 = readl(intel_private.registers+I965_PGETBL_CTL2);
229
    pgetbl_ctl2 &= ~I810_PGETBL_ENABLED;
230
    writel(pgetbl_ctl2, intel_private.registers+I965_PGETBL_CTL2);
231
 
232
    /* write the new ggtt size */
233
    pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
234
    pgetbl_ctl &= ~I965_PGETBL_SIZE_MASK;
235
    pgetbl_ctl |= size_flag;
236
    writel(pgetbl_ctl, intel_private.registers+I810_PGETBL_CTL);
237
}
238
 
239
static unsigned int i965_gtt_total_entries(void)
240
{
241
    int size;
242
    u32 pgetbl_ctl;
243
    u16 gmch_ctl;
244