185397f6bSThomas Zimmermann // SPDX-License-Identifier: GPL-2.0-only
285397f6bSThomas Zimmermann
3877507bbSThomas Zimmermann #include <linux/delay.h>
485397f6bSThomas Zimmermann #include <linux/pci.h>
585397f6bSThomas Zimmermann
6877507bbSThomas Zimmermann #include <drm/drm_atomic.h>
7bc835040SThomas Zimmermann #include <drm/drm_atomic_helper.h>
885397f6bSThomas Zimmermann #include <drm/drm_drv.h>
9bc835040SThomas Zimmermann #include <drm/drm_gem_atomic_helper.h>
10bc835040SThomas Zimmermann #include <drm/drm_probe_helper.h>
1185397f6bSThomas Zimmermann
1285397f6bSThomas Zimmermann #include "mgag200_drv.h"
1385397f6bSThomas Zimmermann
mgag200_g200wb_init_registers(struct mga_device * mdev)141ee181feSThomas Zimmermann void mgag200_g200wb_init_registers(struct mga_device *mdev)
151ee181feSThomas Zimmermann {
161ee181feSThomas Zimmermann static const u8 dacvalue[] = {
171ee181feSThomas Zimmermann MGAG200_DAC_DEFAULT(0x07, 0xc9, 0x1f, 0x00, 0x00, 0x00)
181ee181feSThomas Zimmermann };
191ee181feSThomas Zimmermann
201ee181feSThomas Zimmermann size_t i;
211ee181feSThomas Zimmermann
221ee181feSThomas Zimmermann for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
231ee181feSThomas Zimmermann if ((i <= 0x17) ||
241ee181feSThomas Zimmermann (i == 0x1b) ||
251ee181feSThomas Zimmermann (i == 0x1c) ||
261ee181feSThomas Zimmermann ((i >= 0x1f) && (i <= 0x29)) ||
271ee181feSThomas Zimmermann ((i >= 0x30) && (i <= 0x37)) ||
281ee181feSThomas Zimmermann ((i >= 0x44) && (i <= 0x4e)))
291ee181feSThomas Zimmermann continue;
301ee181feSThomas Zimmermann WREG_DAC(i, dacvalue[i]);
311ee181feSThomas Zimmermann }
321ee181feSThomas Zimmermann
331ee181feSThomas Zimmermann mgag200_init_registers(mdev);
341ee181feSThomas Zimmermann }
351ee181feSThomas Zimmermann
3685397f6bSThomas Zimmermann /*
37877507bbSThomas Zimmermann * PIXPLLC
38877507bbSThomas Zimmermann */
39877507bbSThomas Zimmermann
mgag200_g200wb_pixpllc_atomic_check(struct drm_crtc * crtc,struct drm_atomic_state * new_state)40877507bbSThomas Zimmermann static int mgag200_g200wb_pixpllc_atomic_check(struct drm_crtc *crtc,
41877507bbSThomas Zimmermann struct drm_atomic_state *new_state)
42877507bbSThomas Zimmermann {
43877507bbSThomas Zimmermann static const unsigned int vcomax = 550000;
44877507bbSThomas Zimmermann static const unsigned int vcomin = 150000;
45877507bbSThomas Zimmermann static const unsigned int pllreffreq = 48000;
46877507bbSThomas Zimmermann
47877507bbSThomas Zimmermann struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
48877507bbSThomas Zimmermann struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
49877507bbSThomas Zimmermann long clock = new_crtc_state->mode.clock;
50877507bbSThomas Zimmermann struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
51877507bbSThomas Zimmermann unsigned int delta, tmpdelta;
52877507bbSThomas Zimmermann unsigned int testp, testm, testn;
53877507bbSThomas Zimmermann unsigned int p, m, n, s;
54877507bbSThomas Zimmermann unsigned int computed;
55877507bbSThomas Zimmermann
56877507bbSThomas Zimmermann m = n = p = s = 0;
57877507bbSThomas Zimmermann delta = 0xffffffff;
58877507bbSThomas Zimmermann
59877507bbSThomas Zimmermann for (testp = 1; testp < 9; testp++) {
60877507bbSThomas Zimmermann if (clock * testp > vcomax)
61877507bbSThomas Zimmermann continue;
62877507bbSThomas Zimmermann if (clock * testp < vcomin)
63877507bbSThomas Zimmermann continue;
64877507bbSThomas Zimmermann
65877507bbSThomas Zimmermann for (testm = 1; testm < 17; testm++) {
66877507bbSThomas Zimmermann for (testn = 1; testn < 151; testn++) {
67877507bbSThomas Zimmermann computed = (pllreffreq * testn) / (testm * testp);
68877507bbSThomas Zimmermann if (computed > clock)
69877507bbSThomas Zimmermann tmpdelta = computed - clock;
70877507bbSThomas Zimmermann else
71877507bbSThomas Zimmermann tmpdelta = clock - computed;
72877507bbSThomas Zimmermann if (tmpdelta < delta) {
73877507bbSThomas Zimmermann delta = tmpdelta;
74877507bbSThomas Zimmermann n = testn;
75877507bbSThomas Zimmermann m = testm;
76877507bbSThomas Zimmermann p = testp;
77877507bbSThomas Zimmermann s = 0;
78877507bbSThomas Zimmermann }
79877507bbSThomas Zimmermann }
80877507bbSThomas Zimmermann }
81877507bbSThomas Zimmermann }
82877507bbSThomas Zimmermann
83877507bbSThomas Zimmermann pixpllc->m = m;
84877507bbSThomas Zimmermann pixpllc->n = n;
85877507bbSThomas Zimmermann pixpllc->p = p;
86877507bbSThomas Zimmermann pixpllc->s = s;
87877507bbSThomas Zimmermann
88877507bbSThomas Zimmermann return 0;
89877507bbSThomas Zimmermann }
90877507bbSThomas Zimmermann
mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc * crtc,struct drm_atomic_state * old_state)91877507bbSThomas Zimmermann void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc,
92877507bbSThomas Zimmermann struct drm_atomic_state *old_state)
93877507bbSThomas Zimmermann {
94877507bbSThomas Zimmermann struct drm_device *dev = crtc->dev;
95877507bbSThomas Zimmermann struct mga_device *mdev = to_mga_device(dev);
96877507bbSThomas Zimmermann struct drm_crtc_state *crtc_state = crtc->state;
97877507bbSThomas Zimmermann struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
98877507bbSThomas Zimmermann struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
99877507bbSThomas Zimmermann bool pll_locked = false;
100877507bbSThomas Zimmermann unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
101877507bbSThomas Zimmermann u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
102877507bbSThomas Zimmermann int i, j, tmpcount, vcount;
103877507bbSThomas Zimmermann
104877507bbSThomas Zimmermann pixpllcm = pixpllc->m - 1;
105877507bbSThomas Zimmermann pixpllcn = pixpllc->n - 1;
106877507bbSThomas Zimmermann pixpllcp = pixpllc->p - 1;
107877507bbSThomas Zimmermann pixpllcs = pixpllc->s;
108877507bbSThomas Zimmermann
109877507bbSThomas Zimmermann xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
110877507bbSThomas Zimmermann xpixpllcn = pixpllcn;
111877507bbSThomas Zimmermann xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
112877507bbSThomas Zimmermann
113877507bbSThomas Zimmermann WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
114877507bbSThomas Zimmermann
115877507bbSThomas Zimmermann for (i = 0; i <= 32 && pll_locked == false; i++) {
116877507bbSThomas Zimmermann if (i > 0) {
117877507bbSThomas Zimmermann WREG8(MGAREG_CRTC_INDEX, 0x1e);
118877507bbSThomas Zimmermann tmp = RREG8(MGAREG_CRTC_DATA);
119877507bbSThomas Zimmermann if (tmp < 0xff)
120877507bbSThomas Zimmermann WREG8(MGAREG_CRTC_DATA, tmp+1);
121877507bbSThomas Zimmermann }
122877507bbSThomas Zimmermann
123877507bbSThomas Zimmermann /* set pixclkdis to 1 */
124877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
125877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
126877507bbSThomas Zimmermann tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
127877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
128877507bbSThomas Zimmermann
129877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
130877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
131877507bbSThomas Zimmermann tmp |= MGA1064_REMHEADCTL_CLKDIS;
132877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
133877507bbSThomas Zimmermann
134877507bbSThomas Zimmermann /* select PLL Set C */
135877507bbSThomas Zimmermann tmp = RREG8(MGAREG_MEM_MISC_READ);
136877507bbSThomas Zimmermann tmp |= 0x3 << 2;
137877507bbSThomas Zimmermann WREG8(MGAREG_MEM_MISC_WRITE, tmp);
138877507bbSThomas Zimmermann
139877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
140877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
141877507bbSThomas Zimmermann tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
142877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
143877507bbSThomas Zimmermann
144877507bbSThomas Zimmermann udelay(500);
145877507bbSThomas Zimmermann
146877507bbSThomas Zimmermann /* reset the PLL */
147877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_VREF_CTL);
148877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
149877507bbSThomas Zimmermann tmp &= ~0x04;
150877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
151877507bbSThomas Zimmermann
152877507bbSThomas Zimmermann udelay(50);
153877507bbSThomas Zimmermann
154877507bbSThomas Zimmermann /* program pixel pll register */
155877507bbSThomas Zimmermann WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
156877507bbSThomas Zimmermann WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
157877507bbSThomas Zimmermann WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
158877507bbSThomas Zimmermann
159877507bbSThomas Zimmermann udelay(50);
160877507bbSThomas Zimmermann
161877507bbSThomas Zimmermann /* turn pll on */
162877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_VREF_CTL);
163877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
164877507bbSThomas Zimmermann tmp |= 0x04;
165877507bbSThomas Zimmermann WREG_DAC(MGA1064_VREF_CTL, tmp);
166877507bbSThomas Zimmermann
167877507bbSThomas Zimmermann udelay(500);
168877507bbSThomas Zimmermann
169877507bbSThomas Zimmermann /* select the pixel pll */
170877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
171877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
172877507bbSThomas Zimmermann tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
173877507bbSThomas Zimmermann tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
174877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
175877507bbSThomas Zimmermann
176877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
177877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
178877507bbSThomas Zimmermann tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
179877507bbSThomas Zimmermann tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
180877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
181877507bbSThomas Zimmermann
182877507bbSThomas Zimmermann /* reset dotclock rate bit */
183877507bbSThomas Zimmermann WREG8(MGAREG_SEQ_INDEX, 1);
184877507bbSThomas Zimmermann tmp = RREG8(MGAREG_SEQ_DATA);
185877507bbSThomas Zimmermann tmp &= ~0x8;
186877507bbSThomas Zimmermann WREG8(MGAREG_SEQ_DATA, tmp);
187877507bbSThomas Zimmermann
188877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
189877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
190877507bbSThomas Zimmermann tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
191877507bbSThomas Zimmermann WREG8(DAC_DATA, tmp);
192877507bbSThomas Zimmermann
193877507bbSThomas Zimmermann vcount = RREG8(MGAREG_VCOUNT);
194877507bbSThomas Zimmermann
195877507bbSThomas Zimmermann for (j = 0; j < 30 && pll_locked == false; j++) {
196877507bbSThomas Zimmermann tmpcount = RREG8(MGAREG_VCOUNT);
197877507bbSThomas Zimmermann if (tmpcount < vcount)
198877507bbSThomas Zimmermann vcount = 0;
199877507bbSThomas Zimmermann if ((tmpcount - vcount) > 2)
200877507bbSThomas Zimmermann pll_locked = true;
201877507bbSThomas Zimmermann else
202877507bbSThomas Zimmermann udelay(5);
203877507bbSThomas Zimmermann }
204877507bbSThomas Zimmermann }
205877507bbSThomas Zimmermann
206877507bbSThomas Zimmermann WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
207877507bbSThomas Zimmermann tmp = RREG8(DAC_DATA);
208877507bbSThomas Zimmermann tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
209877507bbSThomas Zimmermann WREG_DAC(MGA1064_REMHEADCTL, tmp);
210877507bbSThomas Zimmermann }
211877507bbSThomas Zimmermann
212877507bbSThomas Zimmermann /*
213bc835040SThomas Zimmermann * Mode-setting pipeline
214bc835040SThomas Zimmermann */
215bc835040SThomas Zimmermann
216bc835040SThomas Zimmermann static const struct drm_plane_helper_funcs mgag200_g200wb_primary_plane_helper_funcs = {
217bc835040SThomas Zimmermann MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
218bc835040SThomas Zimmermann };
219bc835040SThomas Zimmermann
220bc835040SThomas Zimmermann static const struct drm_plane_funcs mgag200_g200wb_primary_plane_funcs = {
221bc835040SThomas Zimmermann MGAG200_PRIMARY_PLANE_FUNCS,
222bc835040SThomas Zimmermann };
223bc835040SThomas Zimmermann
224bc835040SThomas Zimmermann static const struct drm_crtc_helper_funcs mgag200_g200wb_crtc_helper_funcs = {
225bc835040SThomas Zimmermann MGAG200_CRTC_HELPER_FUNCS,
226bc835040SThomas Zimmermann };
227bc835040SThomas Zimmermann
228bc835040SThomas Zimmermann static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = {
229bc835040SThomas Zimmermann MGAG200_CRTC_FUNCS,
230bc835040SThomas Zimmermann };
231bc835040SThomas Zimmermann
232bc835040SThomas Zimmermann static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = {
233bc835040SThomas Zimmermann MGAG200_DAC_ENCODER_FUNCS,
234bc835040SThomas Zimmermann };
235bc835040SThomas Zimmermann
236bc835040SThomas Zimmermann static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = {
237bc835040SThomas Zimmermann MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
238bc835040SThomas Zimmermann };
239bc835040SThomas Zimmermann
240bc835040SThomas Zimmermann static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = {
241bc835040SThomas Zimmermann MGAG200_VGA_CONNECTOR_FUNCS,
242bc835040SThomas Zimmermann };
243bc835040SThomas Zimmermann
mgag200_g200wb_pipeline_init(struct mga_device * mdev)244bc835040SThomas Zimmermann static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
245bc835040SThomas Zimmermann {
246bc835040SThomas Zimmermann struct drm_device *dev = &mdev->base;
247bc835040SThomas Zimmermann struct drm_plane *primary_plane = &mdev->primary_plane;
248bc835040SThomas Zimmermann struct drm_crtc *crtc = &mdev->crtc;
249bc835040SThomas Zimmermann struct drm_encoder *encoder = &mdev->encoder;
250bc835040SThomas Zimmermann struct mga_i2c_chan *i2c = &mdev->i2c;
251bc835040SThomas Zimmermann struct drm_connector *connector = &mdev->connector;
252bc835040SThomas Zimmermann int ret;
253bc835040SThomas Zimmermann
254bc835040SThomas Zimmermann ret = drm_universal_plane_init(dev, primary_plane, 0,
255bc835040SThomas Zimmermann &mgag200_g200wb_primary_plane_funcs,
256bc835040SThomas Zimmermann mgag200_primary_plane_formats,
257bc835040SThomas Zimmermann mgag200_primary_plane_formats_size,
258bc835040SThomas Zimmermann mgag200_primary_plane_fmtmods,
259bc835040SThomas Zimmermann DRM_PLANE_TYPE_PRIMARY, NULL);
260bc835040SThomas Zimmermann if (ret) {
261bc835040SThomas Zimmermann drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
262bc835040SThomas Zimmermann return ret;
263bc835040SThomas Zimmermann }
264bc835040SThomas Zimmermann drm_plane_helper_add(primary_plane, &mgag200_g200wb_primary_plane_helper_funcs);
265bc835040SThomas Zimmermann drm_plane_enable_fb_damage_clips(primary_plane);
266bc835040SThomas Zimmermann
267bc835040SThomas Zimmermann ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
268bc835040SThomas Zimmermann &mgag200_g200wb_crtc_funcs, NULL);
269bc835040SThomas Zimmermann if (ret) {
270bc835040SThomas Zimmermann drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
271bc835040SThomas Zimmermann return ret;
272bc835040SThomas Zimmermann }
273bc835040SThomas Zimmermann drm_crtc_helper_add(crtc, &mgag200_g200wb_crtc_helper_funcs);
274bc835040SThomas Zimmermann
275bc835040SThomas Zimmermann /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
276bc835040SThomas Zimmermann drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
277bc835040SThomas Zimmermann drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
278bc835040SThomas Zimmermann
279bc835040SThomas Zimmermann encoder->possible_crtcs = drm_crtc_mask(crtc);
280bc835040SThomas Zimmermann ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs,
281bc835040SThomas Zimmermann DRM_MODE_ENCODER_DAC, NULL);
282bc835040SThomas Zimmermann if (ret) {
283bc835040SThomas Zimmermann drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
284bc835040SThomas Zimmermann return ret;
285bc835040SThomas Zimmermann }
286bc835040SThomas Zimmermann
287bc835040SThomas Zimmermann ret = mgag200_i2c_init(mdev, i2c);
288bc835040SThomas Zimmermann if (ret) {
289bc835040SThomas Zimmermann drm_err(dev, "failed to add DDC bus: %d\n", ret);
290bc835040SThomas Zimmermann return ret;
291bc835040SThomas Zimmermann }
292bc835040SThomas Zimmermann
293bc835040SThomas Zimmermann ret = drm_connector_init_with_ddc(dev, connector,
294bc835040SThomas Zimmermann &mgag200_g200wb_vga_connector_funcs,
295bc835040SThomas Zimmermann DRM_MODE_CONNECTOR_VGA,
296bc835040SThomas Zimmermann &i2c->adapter);
297bc835040SThomas Zimmermann if (ret) {
298bc835040SThomas Zimmermann drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
299bc835040SThomas Zimmermann return ret;
300bc835040SThomas Zimmermann }
301bc835040SThomas Zimmermann drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs);
302bc835040SThomas Zimmermann
303bc835040SThomas Zimmermann ret = drm_connector_attach_encoder(connector, encoder);
304bc835040SThomas Zimmermann if (ret) {
305bc835040SThomas Zimmermann drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
306bc835040SThomas Zimmermann return ret;
307bc835040SThomas Zimmermann }
308bc835040SThomas Zimmermann
309bc835040SThomas Zimmermann return 0;
310bc835040SThomas Zimmermann }
311bc835040SThomas Zimmermann
312bc835040SThomas Zimmermann /*
31385397f6bSThomas Zimmermann * DRM device
31485397f6bSThomas Zimmermann */
31585397f6bSThomas Zimmermann
316b9a577a4SThomas Zimmermann static const struct mgag200_device_info mgag200_g200wb_device_info =
317da1efdb2SThomas Zimmermann MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false);
318b9a577a4SThomas Zimmermann
319f639f74aSThomas Zimmermann static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
3208aeeb314SThomas Zimmermann .disable_vidrst = mgag200_bmc_disable_vidrst,
3218aeeb314SThomas Zimmermann .enable_vidrst = mgag200_bmc_enable_vidrst,
322877507bbSThomas Zimmermann .pixpllc_atomic_check = mgag200_g200wb_pixpllc_atomic_check,
323877507bbSThomas Zimmermann .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update,
324f639f74aSThomas Zimmermann };
325f639f74aSThomas Zimmermann
mgag200_g200wb_device_create(struct pci_dev * pdev,const struct drm_driver * drv)326*d4a3e50fSThomas Zimmermann struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
32785397f6bSThomas Zimmermann {
32885397f6bSThomas Zimmermann struct mga_device *mdev;
32985397f6bSThomas Zimmermann struct drm_device *dev;
330d45e32c9SThomas Zimmermann resource_size_t vram_available;
33185397f6bSThomas Zimmermann int ret;
33285397f6bSThomas Zimmermann
33385397f6bSThomas Zimmermann mdev = devm_drm_dev_alloc(&pdev->dev, drv, struct mga_device, base);
33485397f6bSThomas Zimmermann if (IS_ERR(mdev))
33585397f6bSThomas Zimmermann return mdev;
33685397f6bSThomas Zimmermann dev = &mdev->base;
33785397f6bSThomas Zimmermann
33885397f6bSThomas Zimmermann pci_set_drvdata(pdev, dev);
33985397f6bSThomas Zimmermann
340ce19021fSThomas Zimmermann ret = mgag200_init_pci_options(pdev, 0x41049120, 0x0000b000);
341ce19021fSThomas Zimmermann if (ret)
342ce19021fSThomas Zimmermann return ERR_PTR(ret);
343ce19021fSThomas Zimmermann
344b62d943eSThomas Zimmermann ret = mgag200_device_preinit(mdev);
34585397f6bSThomas Zimmermann if (ret)
34685397f6bSThomas Zimmermann return ERR_PTR(ret);
34785397f6bSThomas Zimmermann
348*d4a3e50fSThomas Zimmermann ret = mgag200_device_init(mdev, &mgag200_g200wb_device_info,
349f639f74aSThomas Zimmermann &mgag200_g200wb_device_funcs);
35085397f6bSThomas Zimmermann if (ret)
35185397f6bSThomas Zimmermann return ERR_PTR(ret);
35285397f6bSThomas Zimmermann
3531ee181feSThomas Zimmermann mgag200_g200wb_init_registers(mdev);
3541ee181feSThomas Zimmermann
355d45e32c9SThomas Zimmermann vram_available = mgag200_device_probe_vram(mdev);
356d45e32c9SThomas Zimmermann
357bc835040SThomas Zimmermann ret = mgag200_mode_config_init(mdev, vram_available);
35885397f6bSThomas Zimmermann if (ret)
35985397f6bSThomas Zimmermann return ERR_PTR(ret);
36085397f6bSThomas Zimmermann
361bc835040SThomas Zimmermann ret = mgag200_g200wb_pipeline_init(mdev);
362bc835040SThomas Zimmermann if (ret)
363bc835040SThomas Zimmermann return ERR_PTR(ret);
364bc835040SThomas Zimmermann
365bc835040SThomas Zimmermann drm_mode_config_reset(dev);
366bc835040SThomas Zimmermann
36785397f6bSThomas Zimmermann return mdev;
36885397f6bSThomas Zimmermann }
369