Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nv40.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Francisco Jerez.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  */
26 
27 #include <subdev/fb.h>
28 
29 struct nv40_fb_priv {
30  struct nouveau_fb base;
31 };
32 
33 static inline int
34 nv44_graph_class(struct nouveau_device *device)
35 {
36  if ((device->chipset & 0xf0) == 0x60)
37  return 1;
38 
39  return !(0x0baf & (1 << (device->chipset & 0x0f)));
40 }
41 
42 static void
43 nv40_fb_tile_prog(struct nouveau_fb *pfb, int i, struct nouveau_fb_tile *tile)
44 {
45  nv_wr32(pfb, 0x100604 + (i * 0x10), tile->limit);
46  nv_wr32(pfb, 0x100608 + (i * 0x10), tile->pitch);
47  nv_wr32(pfb, 0x100600 + (i * 0x10), tile->addr);
48 }
49 
50 static void
51 nv40_fb_init_gart(struct nv40_fb_priv *priv)
52 {
53  nv_wr32(priv, 0x100800, 0x00000001);
54 }
55 
56 static void
57 nv44_fb_init_gart(struct nv40_fb_priv *priv)
58 {
59  nv_wr32(priv, 0x100850, 0x80000000);
60  nv_wr32(priv, 0x100800, 0x00000001);
61 }
62 
63 static int
64 nv40_fb_init(struct nouveau_object *object)
65 {
66  struct nv40_fb_priv *priv = (void *)object;
67  int ret;
68 
69  ret = nouveau_fb_init(&priv->base);
70  if (ret)
71  return ret;
72 
73  switch (nv_device(priv)->chipset) {
74  case 0x40:
75  case 0x45:
76  nv_mask(priv, 0x10033c, 0x00008000, 0x00000000);
77  break;
78  default:
79  if (nv44_graph_class(nv_device(priv)))
80  nv44_fb_init_gart(priv);
81  else
82  nv40_fb_init_gart(priv);
83  break;
84  }
85 
86  return 0;
87 }
88 
89 static int
90 nv40_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
91  struct nouveau_oclass *oclass, void *data, u32 size,
92  struct nouveau_object **pobject)
93 {
94  struct nouveau_device *device = nv_device(parent);
95  struct nv40_fb_priv *priv;
96  int ret;
97 
98  ret = nouveau_fb_create(parent, engine, oclass, &priv);
99  *pobject = nv_object(priv);
100  if (ret)
101  return ret;
102 
103  /* 0x001218 is actually present on a few other NV4X I looked at,
104  * and even contains sane values matching 0x100474. From looking
105  * at various vbios images however, this isn't the case everywhere.
106  * So, I chose to use the same regs I've seen NVIDIA reading around
107  * the memory detection, hopefully that'll get us the right numbers
108  */
109  if (device->chipset == 0x40) {
110  u32 pbus1218 = nv_rd32(priv, 0x001218);
111  switch (pbus1218 & 0x00000300) {
112  case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_SDRAM; break;
113  case 0x00000100: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
114  case 0x00000200: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
115  case 0x00000300: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
116  }
117  } else
118  if (device->chipset == 0x49 || device->chipset == 0x4b) {
119  u32 pfb914 = nv_rd32(priv, 0x100914);
120  switch (pfb914 & 0x00000003) {
121  case 0x00000000: priv->base.ram.type = NV_MEM_TYPE_DDR1; break;
122  case 0x00000001: priv->base.ram.type = NV_MEM_TYPE_DDR2; break;
123  case 0x00000002: priv->base.ram.type = NV_MEM_TYPE_GDDR3; break;
124  case 0x00000003: break;
125  }
126  } else
127  if (device->chipset != 0x4e) {
128  u32 pfb474 = nv_rd32(priv, 0x100474);
129  if (pfb474 & 0x00000004)
130  priv->base.ram.type = NV_MEM_TYPE_GDDR3;
131  if (pfb474 & 0x00000002)
132  priv->base.ram.type = NV_MEM_TYPE_DDR2;
133  if (pfb474 & 0x00000001)
134  priv->base.ram.type = NV_MEM_TYPE_DDR1;
135  } else {
136  priv->base.ram.type = NV_MEM_TYPE_STOLEN;
137  }
138 
139  priv->base.ram.size = nv_rd32(priv, 0x10020c) & 0xff000000;
140 
141  priv->base.memtype_valid = nv04_fb_memtype_valid;
142  switch (device->chipset) {
143  case 0x40:
144  case 0x45:
145  priv->base.tile.regions = 8;
146  break;
147  case 0x46:
148  case 0x47:
149  case 0x49:
150  case 0x4b:
151  case 0x4c:
152  priv->base.tile.regions = 15;
153  break;
154  default:
155  priv->base.tile.regions = 12;
156  break;
157  }
158  priv->base.tile.init = nv30_fb_tile_init;
159  priv->base.tile.fini = nv30_fb_tile_fini;
160  if (device->chipset == 0x40)
161  priv->base.tile.prog = nv10_fb_tile_prog;
162  else
163  priv->base.tile.prog = nv40_fb_tile_prog;
164 
165  return nouveau_fb_created(&priv->base);
166 }
167 
168 
169 struct nouveau_oclass
171  .handle = NV_SUBDEV(FB, 0x40),
172  .ofuncs = &(struct nouveau_ofuncs) {
173  .ctor = nv40_fb_ctor,
174  .dtor = _nouveau_fb_dtor,
175  .init = nv40_fb_init,
176  .fini = _nouveau_fb_fini,
177  },
178 };