1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "priv.h"
25#include "ram.h"
26
27#include <core/memory.h>
28#include <core/option.h>
29#include <subdev/bios.h>
30#include <subdev/bios/M0203.h>
31#include <engine/gr.h>
32#include <engine/mpeg.h>
33
34bool
35nvkm_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype)
36{
37 return fb->func->memtype_valid(fb, memtype);
38}
39
40void
41nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile)
42{
43 fb->func->tile.fini(fb, region, tile);
44}
45
46void
47nvkm_fb_tile_init(struct nvkm_fb *fb, int region, u32 addr, u32 size,
48 u32 pitch, u32 flags, struct nvkm_fb_tile *tile)
49{
50 fb->func->tile.init(fb, region, addr, size, pitch, flags, tile);
51}
52
53void
54nvkm_fb_tile_prog(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile)
55{
56 struct nvkm_device *device = fb->subdev.device;
57 if (fb->func->tile.prog) {
58 fb->func->tile.prog(fb, region, tile);
59 if (device->gr)
60 nvkm_engine_tile(&device->gr->engine, region);
61 if (device->mpeg)
62 nvkm_engine_tile(device->mpeg, region);
63 }
64}
65
66int
67nvkm_fb_bios_memtype(struct nvkm_bios *bios)
68{
69 struct nvkm_subdev *subdev = &bios->subdev;
70 struct nvkm_device *device = subdev->device;
71 const u8 ramcfg = (nvkm_rd32(device, 0x101000) & 0x0000003c) >> 2;
72 struct nvbios_M0203E M0203E;
73 u8 ver, hdr;
74
75 if (nvbios_M0203Em(bios, ramcfg, &ver, &hdr, &M0203E)) {
76 switch (M0203E.type) {
77 case M0203E_TYPE_DDR2 : return NVKM_RAM_TYPE_DDR2;
78 case M0203E_TYPE_DDR3 : return NVKM_RAM_TYPE_DDR3;
79 case M0203E_TYPE_GDDR3: return NVKM_RAM_TYPE_GDDR3;
80 case M0203E_TYPE_GDDR5: return NVKM_RAM_TYPE_GDDR5;
81 default:
82 nvkm_warn(subdev, "M0203E type %02x\n", M0203E.type);
83 return NVKM_RAM_TYPE_UNKNOWN;
84 }
85 }
86
87 nvkm_warn(subdev, "M0203E not matched!\n");
88 return NVKM_RAM_TYPE_UNKNOWN;
89}
90
91static void
92nvkm_fb_intr(struct nvkm_subdev *subdev)
93{
94 struct nvkm_fb *fb = nvkm_fb(subdev);
95 if (fb->func->intr)
96 fb->func->intr(fb);
97}
98
99static int
100nvkm_fb_oneinit(struct nvkm_subdev *subdev)
101{
102 struct nvkm_fb *fb = nvkm_fb(subdev);
103
104 if (fb->func->ram_new) {
105 int ret = fb->func->ram_new(fb, &fb->ram);
106 if (ret) {
107 nvkm_error(subdev, "vram setup failed, %d\n", ret);
108 return ret;
109 }
110 }
111
112 if (fb->func->oneinit) {
113 int ret = fb->func->oneinit(fb);
114 if (ret)
115 return ret;
116 }
117
118 return 0;
119}
120
121static int
122nvkm_fb_init(struct nvkm_subdev *subdev)
123{
124 struct nvkm_fb *fb = nvkm_fb(subdev);
125 int ret, i;
126
127 if (fb->ram) {
128 ret = nvkm_ram_init(fb->ram);
129 if (ret)
130 return ret;
131 }
132
133 for (i = 0; i < fb->tile.regions; i++)
134 fb->func->tile.prog(fb, i, &fb->tile.region[i]);
135
136 if (fb->func->init)
137 fb->func->init(fb);
138 if (fb->func->init_page)
139 fb->func->init_page(fb);
140 if (fb->func->init_unkn)
141 fb->func->init_unkn(fb);
142 return 0;
143}
144
145static void *
146nvkm_fb_dtor(struct nvkm_subdev *subdev)
147{
148 struct nvkm_fb *fb = nvkm_fb(subdev);
149 int i;
150
151 nvkm_memory_del(&fb->mmu_wr);
152 nvkm_memory_del(&fb->mmu_rd);
153
154 for (i = 0; i < fb->tile.regions; i++)
155 fb->func->tile.fini(fb, i, &fb->tile.region[i]);
156
157 nvkm_ram_del(&fb->ram);
158
159 if (fb->func->dtor)
160 return fb->func->dtor(fb);
161 return fb;
162}
163
164static const struct nvkm_subdev_func
165nvkm_fb = {
166 .dtor = nvkm_fb_dtor,
167 .oneinit = nvkm_fb_oneinit,
168 .init = nvkm_fb_init,
169 .intr = nvkm_fb_intr,
170};
171
172void
173nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
174 int index, struct nvkm_fb *fb)
175{
176 nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev);
177 fb->func = func;
178 fb->tile.regions = fb->func->tile.regions;
179 fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", 0);
180}
181
182int
183nvkm_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device,
184 int index, struct nvkm_fb **pfb)
185{
186 if (!(*pfb = kzalloc(sizeof(**pfb), GFP_KERNEL)))
187 return -ENOMEM;
188 nvkm_fb_ctor(func, device, index, *pfb);
189 return 0;
190}
191