Blame view

drivers/video/cg6.c 21.8 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /* cg6.c: CGSIX (GX, GXplus, TGX) frame buffer driver
   *
50312ce9d   David S. Miller   [SPARC]: Convert ...
3
   * Copyright (C) 2003, 2006 David S. Miller (davem@davemloft.net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
14
   * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
   * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
   * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
   *
   * Driver layout based loosely on tgafb.c, see that file for credits.
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/string.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
  #include <linux/delay.h>
  #include <linux/init.h>
  #include <linux/fb.h>
  #include <linux/mm.h>
6cd5a86b5   Robert Reif   sparc video: remo...
19
  #include <linux/of_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  #include <asm/fbio.h>
  
  #include "sbuslib.h"
  
  /*
   * Local functions.
   */
  
  static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned,
  			 unsigned, struct fb_info *);
  static int cg6_blank(int, struct fb_info *);
  
  static void cg6_imageblit(struct fb_info *, const struct fb_image *);
  static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *);
291d5f303   Robert Reif   cg6: disable curs...
36
  static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  static int cg6_sync(struct fb_info *);
216d526c8   Christoph Hellwig   [PATCH] fbdev: Sa...
38
  static int cg6_mmap(struct fb_info *, struct vm_area_struct *);
67a6680d6   Christoph Hellwig   [PATCH] fbdev: Sa...
39
  static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long);
291d5f303   Robert Reif   cg6: disable curs...
40
  static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
  
  /*
   *  Frame buffer operations
   */
  
  static struct fb_ops cg6_ops = {
  	.owner			= THIS_MODULE,
  	.fb_setcolreg		= cg6_setcolreg,
  	.fb_blank		= cg6_blank,
291d5f303   Robert Reif   cg6: disable curs...
50
  	.fb_pan_display		= cg6_pan_display,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  	.fb_fillrect		= cg6_fillrect,
a140e94d9   Krzysztof Helt   [CG6]: accelerate...
52
  	.fb_copyarea		= cg6_copyarea,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
  	.fb_imageblit		= cg6_imageblit,
  	.fb_sync		= cg6_sync,
  	.fb_mmap		= cg6_mmap,
  	.fb_ioctl		= cg6_ioctl,
9ffb83bcc   Christoph Hellwig   [SBUSFB]: impleme...
57
58
59
  #ifdef CONFIG_COMPAT
  	.fb_compat_ioctl	= sbusfb_compat_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
67
68
  };
  
  /* Offset of interesting structures in the OBIO space */
  /*
   * Brooktree is the video dac and is funny to program on the cg6.
   * (it's even funnier on the cg3)
   * The FBC could be the frame buffer control
   * The FHC could is the frame buffer hardware control.
   */
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
69
70
71
72
73
74
75
76
77
  #define CG6_ROM_OFFSET			0x0UL
  #define CG6_BROOKTREE_OFFSET		0x200000UL
  #define CG6_DHC_OFFSET			0x240000UL
  #define CG6_ALT_OFFSET			0x280000UL
  #define CG6_FHC_OFFSET			0x300000UL
  #define CG6_THC_OFFSET			0x301000UL
  #define CG6_FBC_OFFSET			0x700000UL
  #define CG6_TEC_OFFSET			0x701000UL
  #define CG6_RAM_OFFSET			0x800000UL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  
  /* FHC definitions */
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  #define CG6_FHC_FBID_SHIFT		24
  #define CG6_FHC_FBID_MASK		255
  #define CG6_FHC_REV_SHIFT		20
  #define CG6_FHC_REV_MASK		15
  #define CG6_FHC_FROP_DISABLE		(1 << 19)
  #define CG6_FHC_ROW_DISABLE		(1 << 18)
  #define CG6_FHC_SRC_DISABLE		(1 << 17)
  #define CG6_FHC_DST_DISABLE		(1 << 16)
  #define CG6_FHC_RESET			(1 << 15)
  #define CG6_FHC_LITTLE_ENDIAN		(1 << 13)
  #define CG6_FHC_RES_MASK		(3 << 11)
  #define CG6_FHC_1024			(0 << 11)
  #define CG6_FHC_1152			(1 << 11)
  #define CG6_FHC_1280			(2 << 11)
  #define CG6_FHC_1600			(3 << 11)
  #define CG6_FHC_CPU_MASK		(3 << 9)
  #define CG6_FHC_CPU_SPARC		(0 << 9)
  #define CG6_FHC_CPU_68020		(1 << 9)
  #define CG6_FHC_CPU_386			(2 << 9)
  #define CG6_FHC_TEST			(1 << 8)
  #define CG6_FHC_TEST_X_SHIFT		4
  #define CG6_FHC_TEST_X_MASK		15
  #define CG6_FHC_TEST_Y_SHIFT		0
  #define CG6_FHC_TEST_Y_MASK		15
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  
  /* FBC mode definitions */
  #define CG6_FBC_BLIT_IGNORE		0x00000000
  #define CG6_FBC_BLIT_NOSRC		0x00100000
  #define CG6_FBC_BLIT_SRC		0x00200000
  #define CG6_FBC_BLIT_ILLEGAL		0x00300000
  #define CG6_FBC_BLIT_MASK		0x00300000
  
  #define CG6_FBC_VBLANK			0x00080000
  
  #define CG6_FBC_MODE_IGNORE		0x00000000
  #define CG6_FBC_MODE_COLOR8		0x00020000
  #define CG6_FBC_MODE_COLOR1		0x00040000
  #define CG6_FBC_MODE_HRMONO		0x00060000
  #define CG6_FBC_MODE_MASK		0x00060000
  
  #define CG6_FBC_DRAW_IGNORE		0x00000000
  #define CG6_FBC_DRAW_RENDER		0x00008000
  #define CG6_FBC_DRAW_PICK		0x00010000
  #define CG6_FBC_DRAW_ILLEGAL		0x00018000
  #define CG6_FBC_DRAW_MASK		0x00018000
  
  #define CG6_FBC_BWRITE0_IGNORE		0x00000000
  #define CG6_FBC_BWRITE0_ENABLE		0x00002000
  #define CG6_FBC_BWRITE0_DISABLE		0x00004000
  #define CG6_FBC_BWRITE0_ILLEGAL		0x00006000
  #define CG6_FBC_BWRITE0_MASK		0x00006000
  
  #define CG6_FBC_BWRITE1_IGNORE		0x00000000
  #define CG6_FBC_BWRITE1_ENABLE		0x00000800
  #define CG6_FBC_BWRITE1_DISABLE		0x00001000
  #define CG6_FBC_BWRITE1_ILLEGAL		0x00001800
  #define CG6_FBC_BWRITE1_MASK		0x00001800
  
  #define CG6_FBC_BREAD_IGNORE		0x00000000
  #define CG6_FBC_BREAD_0			0x00000200
  #define CG6_FBC_BREAD_1			0x00000400
  #define CG6_FBC_BREAD_ILLEGAL		0x00000600
  #define CG6_FBC_BREAD_MASK		0x00000600
  
  #define CG6_FBC_BDISP_IGNORE		0x00000000
  #define CG6_FBC_BDISP_0			0x00000080
  #define CG6_FBC_BDISP_1			0x00000100
  #define CG6_FBC_BDISP_ILLEGAL		0x00000180
  #define CG6_FBC_BDISP_MASK		0x00000180
  
  #define CG6_FBC_INDEX_MOD		0x00000040
  #define CG6_FBC_INDEX_MASK		0x00000030
  
  /* THC definitions */
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
154
155
156
157
158
159
160
161
162
163
164
  #define CG6_THC_MISC_REV_SHIFT		16
  #define CG6_THC_MISC_REV_MASK		15
  #define CG6_THC_MISC_RESET		(1 << 12)
  #define CG6_THC_MISC_VIDEO		(1 << 10)
  #define CG6_THC_MISC_SYNC		(1 << 9)
  #define CG6_THC_MISC_VSYNC		(1 << 8)
  #define CG6_THC_MISC_SYNC_ENAB		(1 << 7)
  #define CG6_THC_MISC_CURS_RES		(1 << 6)
  #define CG6_THC_MISC_INT_ENAB		(1 << 5)
  #define CG6_THC_MISC_INT		(1 << 4)
  #define CG6_THC_MISC_INIT		0x9f
291d5f303   Robert Reif   cg6: disable curs...
165
  #define CG6_THC_CURSOFF			((65536-32) | ((65536-32) << 16))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
  
  /* The contents are unknown */
  struct cg6_tec {
50312ce9d   David S. Miller   [SPARC]: Convert ...
169
170
171
  	int tec_matrix;
  	int tec_clip;
  	int tec_vdc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
  };
  
  struct cg6_thc {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
175
176
177
178
179
180
181
182
183
184
185
186
  	u32	thc_pad0[512];
  	u32	thc_hs;		/* hsync timing */
  	u32	thc_hsdvs;
  	u32	thc_hd;
  	u32	thc_vs;		/* vsync timing */
  	u32	thc_vd;
  	u32	thc_refresh;
  	u32	thc_misc;
  	u32	thc_pad1[56];
  	u32	thc_cursxy;	/* cursor x,y position (16 bits each) */
  	u32	thc_cursmask[32];	/* cursor mask bits */
  	u32	thc_cursbits[32];	/* what to show where mask enabled */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
  };
  
  struct cg6_fbc {
50312ce9d   David S. Miller   [SPARC]: Convert ...
190
191
192
  	u32	xxx0[1];
  	u32	mode;
  	u32	clip;
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
193
  	u32	xxx1[1];
50312ce9d   David S. Miller   [SPARC]: Convert ...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  	u32	s;
  	u32	draw;
  	u32	blit;
  	u32	font;
  	u32	xxx2[24];
  	u32	x0, y0, z0, color0;
  	u32	x1, y1, z1, color1;
  	u32	x2, y2, z2, color2;
  	u32	x3, y3, z3, color3;
  	u32	offx, offy;
  	u32	xxx3[2];
  	u32	incx, incy;
  	u32	xxx4[2];
  	u32	clipminx, clipminy;
  	u32	xxx5[2];
  	u32	clipmaxx, clipmaxy;
  	u32	xxx6[2];
  	u32	fg;
  	u32	bg;
  	u32	alu;
  	u32	pm;
  	u32	pixelm;
  	u32	xxx7[2];
  	u32	patalign;
  	u32	pattern[8];
  	u32	xxx8[432];
  	u32	apointx, apointy, apointz;
  	u32	xxx9[1];
  	u32	rpointx, rpointy, rpointz;
  	u32	xxx10[5];
  	u32	pointr, pointg, pointb, pointa;
  	u32	alinex, aliney, alinez;
  	u32	xxx11[1];
  	u32	rlinex, rliney, rlinez;
  	u32	xxx12[5];
  	u32	liner, lineg, lineb, linea;
  	u32	atrix, atriy, atriz;
  	u32	xxx13[1];
  	u32	rtrix, rtriy, rtriz;
  	u32	xxx14[5];
  	u32	trir, trig, trib, tria;
  	u32	aquadx, aquady, aquadz;
  	u32	xxx15[1];
  	u32	rquadx, rquady, rquadz;
  	u32	xxx16[5];
  	u32	quadr, quadg, quadb, quada;
  	u32	arectx, arecty, arectz;
  	u32	xxx17[1];
  	u32	rrectx, rrecty, rrectz;
  	u32	xxx18[5];
  	u32	rectr, rectg, rectb, recta;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
  };
  
  struct bt_regs {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
248
249
250
251
  	u32	addr;
  	u32	color_map;
  	u32	control;
  	u32	cursor;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
258
259
  };
  
  struct cg6_par {
  	spinlock_t		lock;
  	struct bt_regs		__iomem *bt;
  	struct cg6_fbc		__iomem *fbc;
  	struct cg6_thc		__iomem *thc;
  	struct cg6_tec		__iomem *tec;
50312ce9d   David S. Miller   [SPARC]: Convert ...
260
  	u32			__iomem *fhc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
  
  	u32			flags;
  #define CG6_FLAG_BLANKED	0x00000001
50312ce9d   David S. Miller   [SPARC]: Convert ...
264
  	unsigned long		which_io;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
  };
  
  static int cg6_sync(struct fb_info *info)
  {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
269
  	struct cg6_par *par = (struct cg6_par *)info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
277
278
279
280
  	struct cg6_fbc __iomem *fbc = par->fbc;
  	int limit = 10000;
  
  	do {
  		if (!(sbus_readl(&fbc->s) & 0x10000000))
  			break;
  		udelay(10);
  	} while (--limit > 0);
  
  	return 0;
  }
291d5f303   Robert Reif   cg6: disable curs...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  static void cg6_switch_from_graph(struct cg6_par *par)
  {
  	struct cg6_thc __iomem *thc = par->thc;
  	unsigned long flags;
  
  	spin_lock_irqsave(&par->lock, flags);
  
  	/* Hide the cursor. */
  	sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
  
  	spin_unlock_irqrestore(&par->lock, flags);
  }
  
  static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
  {
  	struct cg6_par *par = (struct cg6_par *)info->par;
  
  	/* We just use this to catch switches out of
  	 * graphics mode.
  	 */
  	cg6_switch_from_graph(par);
  
  	if (var->xoffset || var->yoffset || var->vmode)
  		return -EINVAL;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  /**
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
308
   *	cg6_fillrect -	Draws a rectangle on the screen.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
   *
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
310
311
   *	@info: frame buffer structure that represents a single frame buffer
   *	@rect: structure defining the rectagle and operation.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
   */
  static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
  {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
315
  	struct cg6_par *par = (struct cg6_par *)info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
  	struct cg6_fbc __iomem *fbc = par->fbc;
  	unsigned long flags;
  	s32 val;
a140e94d9   Krzysztof Helt   [CG6]: accelerate...
319
  	/* CG6 doesn't handle ROP_XOR */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
321
  
  	spin_lock_irqsave(&par->lock, flags);
a140e94d9   Krzysztof Helt   [CG6]: accelerate...
322

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	cg6_sync(info);
a140e94d9   Krzysztof Helt   [CG6]: accelerate...
324

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  	sbus_writel(rect->color, &fbc->fg);
  	sbus_writel(~(u32)0, &fbc->pixelm);
  	sbus_writel(0xea80ff00, &fbc->alu);
  	sbus_writel(0, &fbc->s);
  	sbus_writel(0, &fbc->clip);
  	sbus_writel(~(u32)0, &fbc->pm);
  	sbus_writel(rect->dy, &fbc->arecty);
  	sbus_writel(rect->dx, &fbc->arectx);
  	sbus_writel(rect->dy + rect->height, &fbc->arecty);
  	sbus_writel(rect->dx + rect->width, &fbc->arectx);
  	do {
  		val = sbus_readl(&fbc->draw);
  	} while (val < 0 && (val & 0x20000000));
  	spin_unlock_irqrestore(&par->lock, flags);
  }
  
  /**
a140e94d9   Krzysztof Helt   [CG6]: accelerate...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
   *	cg6_copyarea - Copies one area of the screen to another area.
   *
   *	@info: frame buffer structure that represents a single frame buffer
   *	@area: Structure providing the data to copy the framebuffer contents
   *		from one region to another.
   *
   *	This drawing operation copies a rectangular area from one area of the
   *	screen to another area.
   */
  static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area)
  {
  	struct cg6_par *par = (struct cg6_par *)info->par;
  	struct cg6_fbc __iomem *fbc = par->fbc;
  	unsigned long flags;
  	int i;
  
  	spin_lock_irqsave(&par->lock, flags);
  
  	cg6_sync(info);
  
  	sbus_writel(0xff, &fbc->fg);
  	sbus_writel(0x00, &fbc->bg);
  	sbus_writel(~0, &fbc->pixelm);
  	sbus_writel(0xe880cccc, &fbc->alu);
  	sbus_writel(0, &fbc->s);
  	sbus_writel(0, &fbc->clip);
  
  	sbus_writel(area->sy, &fbc->y0);
  	sbus_writel(area->sx, &fbc->x0);
  	sbus_writel(area->sy + area->height - 1, &fbc->y1);
  	sbus_writel(area->sx + area->width - 1, &fbc->x1);
  	sbus_writel(area->dy, &fbc->y2);
  	sbus_writel(area->dx, &fbc->x2);
  	sbus_writel(area->dy + area->height - 1, &fbc->y3);
  	sbus_writel(area->dx + area->width - 1, &fbc->x3);
  	do {
  		i = sbus_readl(&fbc->blit);
  	} while (i < 0 && (i & 0x20000000));
  	spin_unlock_irqrestore(&par->lock, flags);
  }
  
  /**
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
384
   *	cg6_imageblit -	Copies a image from system memory to the screen.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
   *
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
386
387
   *	@info: frame buffer structure that represents a single frame buffer
   *	@image: structure defining the image.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
   */
  static void cg6_imageblit(struct fb_info *info, const struct fb_image *image)
  {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
391
  	struct cg6_par *par = (struct cg6_par *)info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
  	struct cg6_fbc __iomem *fbc = par->fbc;
  	const u8 *data = image->data;
  	unsigned long flags;
  	u32 x, y;
  	int i, width;
  
  	if (image->depth > 1) {
  		cfb_imageblit(info, image);
  		return;
  	}
  
  	spin_lock_irqsave(&par->lock, flags);
  
  	cg6_sync(info);
  
  	sbus_writel(image->fg_color, &fbc->fg);
  	sbus_writel(image->bg_color, &fbc->bg);
  	sbus_writel(0x140000, &fbc->mode);
  	sbus_writel(0xe880fc30, &fbc->alu);
  	sbus_writel(~(u32)0, &fbc->pixelm);
  	sbus_writel(0, &fbc->s);
  	sbus_writel(0, &fbc->clip);
  	sbus_writel(0xff, &fbc->pm);
  	sbus_writel(32, &fbc->incx);
  	sbus_writel(0, &fbc->incy);
  
  	x = image->dx;
  	y = image->dy;
  	for (i = 0; i < image->height; i++) {
  		width = image->width;
  
  		while (width >= 32) {
  			u32 val;
  
  			sbus_writel(y, &fbc->y0);
  			sbus_writel(x, &fbc->x0);
  			sbus_writel(x + 32 - 1, &fbc->x1);
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
429

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
  			val = ((u32)data[0] << 24) |
  			      ((u32)data[1] << 16) |
  			      ((u32)data[2] <<  8) |
  			      ((u32)data[3] <<  0);
  			sbus_writel(val, &fbc->font);
  
  			data += 4;
  			x += 32;
  			width -= 32;
  		}
  		if (width) {
  			u32 val;
  
  			sbus_writel(y, &fbc->y0);
  			sbus_writel(x, &fbc->x0);
  			sbus_writel(x + width - 1, &fbc->x1);
  			if (width <= 8) {
  				val = (u32) data[0] << 24;
  				data += 1;
  			} else if (width <= 16) {
  				val = ((u32) data[0] << 24) |
  				      ((u32) data[1] << 16);
  				data += 2;
  			} else {
  				val = ((u32) data[0] << 24) |
  				      ((u32) data[1] << 16) |
  				      ((u32) data[2] <<  8);
  				data += 3;
  			}
  			sbus_writel(val, &fbc->font);
  		}
  
  		y += 1;
  		x = image->dx;
  	}
  
  	spin_unlock_irqrestore(&par->lock, flags);
  }
  
  /**
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
470
471
472
473
474
475
476
477
   *	cg6_setcolreg - Sets a color register.
   *
   *	@regno: boolean, 0 copy local, 1 get_user() function
   *	@red: frame buffer colormap structure
   *	@green: The green value which can be up to 16 bits wide
   *	@blue:  The blue value which can be up to 16 bits wide.
   *	@transp: If supported the alpha value which can be up to 16 bits wide.
   *	@info: frame buffer info structure
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
482
   */
  static int cg6_setcolreg(unsigned regno,
  			 unsigned red, unsigned green, unsigned blue,
  			 unsigned transp, struct fb_info *info)
  {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
483
  	struct cg6_par *par = (struct cg6_par *)info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
  	struct bt_regs __iomem *bt = par->bt;
  	unsigned long flags;
  
  	if (regno >= 256)
  		return 1;
  
  	red >>= 8;
  	green >>= 8;
  	blue >>= 8;
  
  	spin_lock_irqsave(&par->lock, flags);
  
  	sbus_writel((u32)regno << 24, &bt->addr);
  	sbus_writel((u32)red << 24, &bt->color_map);
  	sbus_writel((u32)green << 24, &bt->color_map);
  	sbus_writel((u32)blue << 24, &bt->color_map);
  
  	spin_unlock_irqrestore(&par->lock, flags);
  
  	return 0;
  }
  
  /**
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
507
508
509
510
   *	cg6_blank - Blanks the display.
   *
   *	@blank_mode: the blank mode we want.
   *	@info: frame buffer structure that represents a single frame buffer
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
   */
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
512
  static int cg6_blank(int blank, struct fb_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
514
  	struct cg6_par *par = (struct cg6_par *)info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
  	struct cg6_thc __iomem *thc = par->thc;
  	unsigned long flags;
  	u32 val;
  
  	spin_lock_irqsave(&par->lock, flags);
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
520
  	val = sbus_readl(&thc->thc_misc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
  
  	switch (blank) {
  	case FB_BLANK_UNBLANK: /* Unblanking */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
524
  		val |= CG6_THC_MISC_VIDEO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
530
531
  		par->flags &= ~CG6_FLAG_BLANKED;
  		break;
  
  	case FB_BLANK_NORMAL: /* Normal blanking */
  	case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */
  	case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */
  	case FB_BLANK_POWERDOWN: /* Poweroff */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  		val &= ~CG6_THC_MISC_VIDEO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
535
  		par->flags |= CG6_FLAG_BLANKED;
  		break;
  	}
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
536
  	sbus_writel(val, &thc->thc_misc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
  	spin_unlock_irqrestore(&par->lock, flags);
  
  	return 0;
  }
  
  static struct sbus_mmap_map cg6_mmap_map[] = {
  	{
  		.voff	= CG6_FBC,
  		.poff	= CG6_FBC_OFFSET,
  		.size	= PAGE_SIZE
  	},
  	{
  		.voff	= CG6_TEC,
  		.poff	= CG6_TEC_OFFSET,
  		.size	= PAGE_SIZE
  	},
  	{
  		.voff	= CG6_BTREGS,
  		.poff	= CG6_BROOKTREE_OFFSET,
  		.size	= PAGE_SIZE
  	},
  	{
  		.voff	= CG6_FHC,
  		.poff	= CG6_FHC_OFFSET,
  		.size	= PAGE_SIZE
  	},
  	{
  		.voff	= CG6_THC,
  		.poff	= CG6_THC_OFFSET,
  		.size	= PAGE_SIZE
  	},
  	{
  		.voff	= CG6_ROM,
  		.poff	= CG6_ROM_OFFSET,
  		.size	= 0x10000
  	},
  	{
  		.voff	= CG6_RAM,
  		.poff	= CG6_RAM_OFFSET,
  		.size	= SBUS_MMAP_FBSIZE(1)
  	},
  	{
  		.voff	= CG6_DHC,
  		.poff	= CG6_DHC_OFFSET,
  		.size	= 0x40000
  	},
  	{ .size	= 0 }
  };
216d526c8   Christoph Hellwig   [PATCH] fbdev: Sa...
585
  static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
589
  {
  	struct cg6_par *par = (struct cg6_par *)info->par;
  
  	return sbusfb_mmap_helper(cg6_mmap_map,
963b916c1   Krzysztof Helt   cg6: use standard...
590
  				  info->fix.smem_start, info->fix.smem_len,
50312ce9d   David S. Miller   [SPARC]: Convert ...
591
  				  par->which_io, vma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
  }
67a6680d6   Christoph Hellwig   [PATCH] fbdev: Sa...
593
  static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  	return sbusfb_ioctl_helper(cmd, arg, info,
963b916c1   Krzysztof Helt   cg6: use standard...
596
  				   FBTYPE_SUNFAST_COLOR, 8, info->fix.smem_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
599
600
601
  }
  
  /*
   *  Initialisation
   */
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
602
  static void __devinit cg6_init_fix(struct fb_info *info, int linebytes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
607
608
  {
  	struct cg6_par *par = (struct cg6_par *)info->par;
  	const char *cg6_cpu_name, *cg6_card_name;
  	u32 conf;
  
  	conf = sbus_readl(par->fhc);
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
609
  	switch (conf & CG6_FHC_CPU_MASK) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
614
615
616
617
618
619
620
  	case CG6_FHC_CPU_SPARC:
  		cg6_cpu_name = "sparc";
  		break;
  	case CG6_FHC_CPU_68020:
  		cg6_cpu_name = "68020";
  		break;
  	default:
  		cg6_cpu_name = "i386";
  		break;
  	};
  	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
963b916c1   Krzysztof Helt   cg6: use standard...
621
  		if (info->fix.smem_len <= 0x100000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
  			cg6_card_name = "TGX";
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
623
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  			cg6_card_name = "TGX+";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  	} else {
963b916c1   Krzysztof Helt   cg6: use standard...
626
  		if (info->fix.smem_len <= 0x100000)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  			cg6_card_name = "GX";
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
628
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  			cg6_card_name = "GX+";
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
632
  	}
  
  	sprintf(info->fix.id, "%s %s", cg6_card_name, cg6_cpu_name);
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
633
  	info->fix.id[sizeof(info->fix.id) - 1] = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
637
638
639
640
641
642
643
  
  	info->fix.type = FB_TYPE_PACKED_PIXELS;
  	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  
  	info->fix.line_length = linebytes;
  
  	info->fix.accel = FB_ACCEL_SUN_CGSIX;
  }
  
  /* Initialize Brooktree DAC */
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
644
  static void __devinit cg6_bt_init(struct cg6_par *par)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
  {
  	struct bt_regs __iomem *bt = par->bt;
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
647
  	sbus_writel(0x04 << 24, &bt->addr);	 /* color planes */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
649
650
  	sbus_writel(0xff << 24, &bt->control);
  	sbus_writel(0x05 << 24, &bt->addr);
  	sbus_writel(0x00 << 24, &bt->control);
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
651
  	sbus_writel(0x06 << 24, &bt->addr);	 /* overlay plane */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
652
653
654
655
  	sbus_writel(0x73 << 24, &bt->control);
  	sbus_writel(0x07 << 24, &bt->addr);
  	sbus_writel(0x00 << 24, &bt->control);
  }
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
656
  static void __devinit cg6_chip_init(struct fb_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
  {
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
658
  	struct cg6_par *par = (struct cg6_par *)info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
  	struct cg6_tec __iomem *tec = par->tec;
  	struct cg6_fbc __iomem *fbc = par->fbc;
291d5f303   Robert Reif   cg6: disable curs...
661
  	struct cg6_thc __iomem *thc = par->thc;
806f7bf60   David S. Miller   [SBUSFB]: Kill 'l...
662
  	u32 rev, conf, mode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
  	int i;
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
664

291d5f303   Robert Reif   cg6: disable curs...
665
666
  	/* Hide the cursor. */
  	sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  	/* Turn off stuff in the Transform Engine. */
  	sbus_writel(0, &tec->tec_matrix);
  	sbus_writel(0, &tec->tec_clip);
  	sbus_writel(0, &tec->tec_vdc);
  
  	/* Take care of bugs in old revisions. */
  	rev = (sbus_readl(par->fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
  	if (rev < 5) {
  		conf = (sbus_readl(par->fhc) & CG6_FHC_RES_MASK) |
  			CG6_FHC_CPU_68020 | CG6_FHC_TEST |
  			(11 << CG6_FHC_TEST_X_SHIFT) |
  			(11 << CG6_FHC_TEST_Y_SHIFT);
  		if (rev < 2)
  			conf |= CG6_FHC_DST_DISABLE;
  		sbus_writel(conf, par->fhc);
  	}
  
  	/* Set things in the FBC. Bad things appear to happen if we do
  	 * back to back store/loads on the mode register, so copy it
  	 * out instead. */
  	mode = sbus_readl(&fbc->mode);
  	do {
  		i = sbus_readl(&fbc->s);
  	} while (i & 0x10000000);
  	mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
692
693
694
  		  CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
  		  CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
  		  CG6_FBC_BDISP_MASK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
  	mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
696
697
698
  		 CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
  		 CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
  		 CG6_FBC_BDISP_0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
702
703
704
705
706
707
  	sbus_writel(mode, &fbc->mode);
  
  	sbus_writel(0, &fbc->clip);
  	sbus_writel(0, &fbc->offx);
  	sbus_writel(0, &fbc->offy);
  	sbus_writel(0, &fbc->clipminx);
  	sbus_writel(0, &fbc->clipminy);
  	sbus_writel(info->var.xres - 1, &fbc->clipmaxx);
  	sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
  }
2dc115813   Grant Likely   of/device: Replac...
709
  static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
710
  			   struct cg6_par *par)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711
  {
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
712
713
714
715
716
717
718
719
720
721
722
723
  	if (par->fbc)
  		of_iounmap(&op->resource[0], par->fbc, 4096);
  	if (par->tec)
  		of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
  	if (par->thc)
  		of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
  	if (par->bt)
  		of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
  	if (par->fhc)
  		of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
  
  	if (info->screen_base)
963b916c1   Krzysztof Helt   cg6: use standard...
724
725
  		of_iounmap(&op->resource[0], info->screen_base,
  			   info->fix.smem_len);
50312ce9d   David S. Miller   [SPARC]: Convert ...
726
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
727

28541d0f1   Grant Likely   dt/video: Elimina...
728
  static int __devinit cg6_probe(struct platform_device *op)
50312ce9d   David S. Miller   [SPARC]: Convert ...
729
  {
61c7a080a   Grant Likely   of: Always use 's...
730
  	struct device_node *dp = op->dev.of_node;
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
731
732
  	struct fb_info *info;
  	struct cg6_par *par;
50312ce9d   David S. Miller   [SPARC]: Convert ...
733
  	int linebytes, err;
3fc701d5d   Krzysztof Helt   [CG6]: fix memory...
734
  	int dblbuf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
736
737
738
739
740
741
  	info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
  
  	err = -ENOMEM;
  	if (!info)
  		goto out_err;
  	par = info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
743
  	spin_lock_init(&par->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744

963b916c1   Krzysztof Helt   cg6: use standard...
745
  	info->fix.smem_start = op->resource[0].start;
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
746
  	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
747

6cd5a86b5   Robert Reif   sparc video: remo...
748
  	sbusfb_fill_var(&info->var, dp, 8);
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
749
750
751
  	info->var.red.length = 8;
  	info->var.green.length = 8;
  	info->var.blue.length = 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752

50312ce9d   David S. Miller   [SPARC]: Convert ...
753
  	linebytes = of_getintprop_default(dp, "linebytes",
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
754
  					  info->var.xres);
963b916c1   Krzysztof Helt   cg6: use standard...
755
  	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
3fc701d5d   Krzysztof Helt   [CG6]: fix memory...
756
757
758
  
  	dblbuf = of_getintprop_default(dp, "dblbuf", 0);
  	if (dblbuf)
963b916c1   Krzysztof Helt   cg6: use standard...
759
  		info->fix.smem_len *= 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
761
  	par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
762
  				4096, "cgsix fbc");
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
763
  	par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
764
  				sizeof(struct cg6_tec), "cgsix tec");
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
765
  	par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
766
  				sizeof(struct cg6_thc), "cgsix thc");
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
767
  	par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
768
  				sizeof(struct bt_regs), "cgsix dac");
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
769
  	par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
6993bea1b   Krzysztof Helt   [CG6]: code cleanup
770
  				sizeof(u32), "cgsix fhc");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
772
  	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
a140e94d9   Krzysztof Helt   [CG6]: accelerate...
773
774
  			FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
  			FBINFO_READS_FAST;
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
775
  	info->fbops = &cg6_ops;
50312ce9d   David S. Miller   [SPARC]: Convert ...
776

6993bea1b   Krzysztof Helt   [CG6]: code cleanup
777
  	info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
963b916c1   Krzysztof Helt   cg6: use standard...
778
  					info->fix.smem_len, "cgsix ram");
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
779
780
781
  	if (!par->fbc || !par->tec || !par->thc ||
  	    !par->bt || !par->fhc || !info->screen_base)
  		goto out_unmap_regs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
783
  	info->var.accel_flags = FB_ACCELF_TEXT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
785
786
  	cg6_bt_init(par);
  	cg6_chip_init(info);
59f7137a1   Robert Reif   sparc video: make...
787
  	cg6_blank(FB_BLANK_UNBLANK, info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
789
790
  	if (fb_alloc_cmap(&info->cmap, 256, 0))
  		goto out_unmap_regs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
792
793
  	fb_set_cmap(&info->cmap, info);
  	cg6_init_fix(info, linebytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
795
796
797
  	err = register_framebuffer(info);
  	if (err < 0)
  		goto out_dealloc_cmap;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
799
  	dev_set_drvdata(&op->dev, info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800

194f1a68b   Robert Reif   sparc: video driv...
801
802
  	printk(KERN_INFO "%s: CGsix [%s] at %lx:%lx
  ",
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
803
  	       dp->full_name, info->fix.id,
963b916c1   Krzysztof Helt   cg6: use standard...
804
  	       par->which_io, info->fix.smem_start);
50312ce9d   David S. Miller   [SPARC]: Convert ...
805
806
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
808
809
810
811
812
  out_dealloc_cmap:
  	fb_dealloc_cmap(&info->cmap);
  
  out_unmap_regs:
  	cg6_unmap_regs(op, info, par);
6359691d7   Axel Lin   video: add missin...
813
  	framebuffer_release(info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
815
816
  out_err:
  	return err;
50312ce9d   David S. Miller   [SPARC]: Convert ...
817
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818

2dc115813   Grant Likely   of/device: Replac...
819
  static int __devexit cg6_remove(struct platform_device *op)
50312ce9d   David S. Miller   [SPARC]: Convert ...
820
  {
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
821
822
  	struct fb_info *info = dev_get_drvdata(&op->dev);
  	struct cg6_par *par = info->par;
50312ce9d   David S. Miller   [SPARC]: Convert ...
823

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
824
825
  	unregister_framebuffer(info);
  	fb_dealloc_cmap(&info->cmap);
50312ce9d   David S. Miller   [SPARC]: Convert ...
826

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
827
  	cg6_unmap_regs(op, info, par);
50312ce9d   David S. Miller   [SPARC]: Convert ...
828

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
829
  	framebuffer_release(info);
50312ce9d   David S. Miller   [SPARC]: Convert ...
830

e3a411a3d   David S. Miller   [SPARC64]: Fix of...
831
  	dev_set_drvdata(&op->dev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
833
834
  
  	return 0;
  }
fd098316e   David S. Miller   sparc: Annotate o...
835
  static const struct of_device_id cg6_match[] = {
50312ce9d   David S. Miller   [SPARC]: Convert ...
836
837
838
839
840
841
842
843
844
  	{
  		.name = "cgsix",
  	},
  	{
  		.name = "cgthree+",
  	},
  	{},
  };
  MODULE_DEVICE_TABLE(of, cg6_match);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845

28541d0f1   Grant Likely   dt/video: Elimina...
846
  static struct platform_driver cg6_driver = {
4018294b5   Grant Likely   of: Remove duplic...
847
848
849
850
851
  	.driver = {
  		.name = "cg6",
  		.owner = THIS_MODULE,
  		.of_match_table = cg6_match,
  	},
50312ce9d   David S. Miller   [SPARC]: Convert ...
852
853
854
  	.probe		= cg6_probe,
  	.remove		= __devexit_p(cg6_remove),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855

50312ce9d   David S. Miller   [SPARC]: Convert ...
856
857
858
859
  static int __init cg6_init(void)
  {
  	if (fb_get_options("cg6fb", NULL))
  		return -ENODEV;
28541d0f1   Grant Likely   dt/video: Elimina...
860
  	return platform_driver_register(&cg6_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
861
  }
50312ce9d   David S. Miller   [SPARC]: Convert ...
862
  static void __exit cg6_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
  {
28541d0f1   Grant Likely   dt/video: Elimina...
864
  	platform_driver_unregister(&cg6_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
865
866
867
  }
  
  module_init(cg6_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
  module_exit(cg6_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
870
  
  MODULE_DESCRIPTION("framebuffer driver for CGsix chipsets");
50312ce9d   David S. Miller   [SPARC]: Convert ...
871
872
  MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
  MODULE_VERSION("2.0");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
  MODULE_LICENSE("GPL");