Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nv04.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/devinit.h>
28 #include <subdev/vga.h>
29 
30 #include "fbmem.h"
31 
34  int owner;
35 };
36 
37 static void
38 nv04_devinit_meminit(struct nouveau_devinit *devinit)
39 {
40  struct nv04_devinit_priv *priv = (void *)devinit;
41  u32 patt = 0xdeadbeef;
42  struct io_mapping *fb;
43  int i;
44 
45  /* Map the framebuffer aperture */
46  fb = fbmem_init(nv_device(priv)->pdev);
47  if (!fb) {
48  nv_error(priv, "failed to map fb\n");
49  return;
50  }
51 
52  /* Sequencer and refresh off */
53  nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) | 0x20);
55 
56  nv_mask(priv, NV04_PFB_BOOT_0, ~0,
60 
61  for (i = 0; i < 4; i++)
62  fbmem_poke(fb, 4 * i, patt);
63 
64  fbmem_poke(fb, 0x400000, patt + 1);
65 
66  if (fbmem_peek(fb, 0) == patt + 1) {
67  nv_mask(priv, NV04_PFB_BOOT_0,
70  nv_mask(priv, NV04_PFB_DEBUG_0,
72 
73  for (i = 0; i < 4; i++)
74  fbmem_poke(fb, 4 * i, patt);
75 
76  if ((fbmem_peek(fb, 0xc) & 0xffff) != (patt & 0xffff))
77  nv_mask(priv, NV04_PFB_BOOT_0,
81  } else
82  if ((fbmem_peek(fb, 0xc) & 0xffff0000) != (patt & 0xffff0000)) {
83  nv_mask(priv, NV04_PFB_BOOT_0,
87  } else
88  if (fbmem_peek(fb, 0) != patt) {
89  if (fbmem_readback(fb, 0x800000, patt))
90  nv_mask(priv, NV04_PFB_BOOT_0,
93  else
94  nv_mask(priv, NV04_PFB_BOOT_0,
97 
100  } else
101  if (!fbmem_readback(fb, 0x800000, patt)) {
104 
105  }
106 
107  /* Refresh on, sequencer on */
109  nv_wrvgas(priv, 0, 1, nv_rdvgas(priv, 0, 1) & ~0x20);
110  fbmem_fini(fb);
111 }
112 
113 static int
114 nv04_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
115  struct nouveau_oclass *oclass, void *data, u32 size,
116  struct nouveau_object **pobject)
117 {
118  struct nv04_devinit_priv *priv;
119  int ret;
120 
121  ret = nouveau_devinit_create(parent, engine, oclass, &priv);
122  *pobject = nv_object(priv);
123  if (ret)
124  return ret;
125 
126  priv->base.meminit = nv04_devinit_meminit;
127  priv->owner = -1;
128  return 0;
129 }
130 
131 void
133 {
134  struct nv04_devinit_priv *priv = (void *)object;
135 
136  /* restore vga owner saved at first init, and lock crtc regs */
137  nv_wrvgaowner(priv, priv->owner);
138  nv_lockvgac(priv, true);
139 
141 }
142 
143 int
145 {
146  struct nv04_devinit_priv *priv = (void *)object;
147 
148  if (!priv->base.post) {
149  u32 htotal = nv_rdvgac(priv, 0, 0x06);
150  htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x01) << 8;
151  htotal |= (nv_rdvgac(priv, 0, 0x07) & 0x20) << 4;
152  htotal |= (nv_rdvgac(priv, 0, 0x25) & 0x01) << 10;
153  htotal |= (nv_rdvgac(priv, 0, 0x41) & 0x01) << 11;
154  if (!htotal) {
155  nv_info(priv, "adaptor not initialised\n");
156  priv->base.post = true;
157  }
158  }
159 
160  return nouveau_devinit_init(&priv->base);
161 }
162 
163 int
165 {
166  struct nv04_devinit_priv *priv = (void *)object;
167 
168  /* make i2c busses accessible */
169  nv_mask(priv, 0x000200, 0x00000001, 0x00000001);
170 
171  /* unlock extended vga crtc regs, and unslave crtcs */
172  nv_lockvgac(priv, false);
173  if (priv->owner < 0)
174  priv->owner = nv_rdvgaowner(priv);
175  nv_wrvgaowner(priv, 0);
176 
177  return nouveau_devinit_fini(&priv->base, suspend);
178 }
179 
180 struct nouveau_oclass
182  .handle = NV_SUBDEV(DEVINIT, 0x04),
183  .ofuncs = &(struct nouveau_ofuncs) {
184  .ctor = nv04_devinit_ctor,
185  .dtor = nv04_devinit_dtor,
186  .init = nv04_devinit_init,
187  .fini = nv04_devinit_fini,
188  },
189 };