Blame view

drivers/video/pmagb-b-fb.c 10.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
2
   *	linux/drivers/video/pmagb-b-fb.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
   *
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
4
5
   *	PMAGB-B TURBOchannel Smart Frame Buffer (SFB) card support,
   *	derived from:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
   *	"HP300 Topcat framebuffer support (derived from macfb of all things)
   *	Phil Blundell <philb@gnu.org> 1998", the original code can be
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
8
   *	found in the file hpfb.c in the same directory.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
   *
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
10
11
12
   *	DECstation related code Copyright (C) 1999, 2000, 2001 by
   *	Michael Engel <engel@unix-ag.org>,
   *	Karsten Merker <merker@linuxtag.org> and
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   *	Harald Koerfgen.
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
14
   *	Copyright (c) 2005, 2006  Maciej W. Rozycki
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
   *
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
16
17
18
   *	This file is subject to the terms and conditions of the GNU General
   *	Public License.  See the file COPYING in the main directory of this
   *	archive for more details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
   */
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
20
  #include <linux/compiler.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
  #include <linux/delay.h>
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
22
  #include <linux/errno.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  #include <linux/fb.h>
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
24
25
26
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
27
  #include <linux/tc.h>
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
28
  #include <linux/types.h>
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
29
30
  #include <asm/io.h>
  #include <asm/system.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  #include <video/pmagb-b-fb.h>
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
32
33
  
  struct pmagbbfb_par {
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
34
35
36
37
38
39
40
  	volatile void __iomem *mmio;
  	volatile void __iomem *smem;
  	volatile u32 __iomem *sfb;
  	volatile u32 __iomem *dac;
  	unsigned int osc0;
  	unsigned int osc1;
  	int slot;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42

5b1638d94   Ralf Baechle   VIDEO: PMAGB-B: F...
43
  static struct fb_var_screeninfo pmagbbfb_defined __devinitdata = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
  	.bits_per_pixel	= 8,
  	.red.length	= 8,
  	.green.length	= 8,
  	.blue.length	= 8,
  	.activate	= FB_ACTIVATE_NOW,
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
49
50
  	.height		= -1,
  	.width		= -1,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  	.accel_flags	= FB_ACCEL_NONE,
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
52
  	.sync		= FB_SYNC_ON_GREEN,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
  	.vmode		= FB_VMODE_NONINTERLACED,
  };
5b1638d94   Ralf Baechle   VIDEO: PMAGB-B: F...
55
  static struct fb_fix_screeninfo pmagbbfb_fix __devinitdata = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
  	.id		= "PMAGB-BA",
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
57
  	.smem_len	= (2048 * 1024),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  	.type		= FB_TYPE_PACKED_PIXELS,
  	.visual		= FB_VISUAL_PSEUDOCOLOR,
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
60
61
62
63
64
65
66
  	.mmio_len	= PMAGB_B_FBMEM,
  };
  
  
  static inline void sfb_write(struct pmagbbfb_par *par, unsigned int reg, u32 v)
  {
  	writel(v, par->sfb + reg / 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  }
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
68
69
70
71
72
73
  static inline u32 sfb_read(struct pmagbbfb_par *par, unsigned int reg)
  {
  	return readl(par->sfb + reg / 4);
  }
  
  static inline void dac_write(struct pmagbbfb_par *par, unsigned int reg, u8 v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  {
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
75
  	writeb(v, par->dac + reg / 4);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  }
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
77
78
79
80
81
82
83
84
85
  static inline u8 dac_read(struct pmagbbfb_par *par, unsigned int reg)
  {
  	return readb(par->dac + reg / 4);
  }
  
  static inline void gp0_write(struct pmagbbfb_par *par, u32 v)
  {
  	writel(v, par->mmio + PMAGB_B_GP0);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  /*
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
87
   * Set the palette.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
   */
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
89
90
91
  static int pmagbbfb_setcolreg(unsigned int regno, unsigned int red,
  			      unsigned int green, unsigned int blue,
  			      unsigned int transp, struct fb_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  {
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
93
  	struct pmagbbfb_par *par = info->par;
2f390380c   Krzysztof Helt   fbdev: add palett...
94
95
  	if (regno >= info->cmap.len)
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  
  	red   >>= 8;	/* The cmap fields are 16 bits    */
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
98
  	green >>= 8;	/* wide, but the hardware colormap */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  	blue  >>= 8;	/* registers are only 8 bits wide */
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
100
101
102
103
104
105
106
107
108
  	mb();
  	dac_write(par, BT459_ADDR_LO, regno);
  	dac_write(par, BT459_ADDR_HI, 0x00);
  	wmb();
  	dac_write(par, BT459_CMAP, red);
  	wmb();
  	dac_write(par, BT459_CMAP, green);
  	wmb();
  	dac_write(par, BT459_CMAP, blue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
117
  	return 0;
  }
  
  static struct fb_ops pmagbbfb_ops = {
  	.owner		= THIS_MODULE,
  	.fb_setcolreg	= pmagbbfb_setcolreg,
  	.fb_fillrect	= cfb_fillrect,
  	.fb_copyarea	= cfb_copyarea,
  	.fb_imageblit	= cfb_imageblit,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  };
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  
  /*
   * Turn the hardware cursor off.
   */
  static void __init pmagbbfb_erase_cursor(struct fb_info *info)
  {
  	struct pmagbbfb_par *par = info->par;
  
  	mb();
  	dac_write(par, BT459_ADDR_LO, 0x00);
  	dac_write(par, BT459_ADDR_HI, 0x03);
  	wmb();
  	dac_write(par, BT459_DATA, 0x00);
  }
  
  /*
   * Set up screen parameters.
   */
5b1638d94   Ralf Baechle   VIDEO: PMAGB-B: F...
137
  static void __devinit pmagbbfb_screen_setup(struct fb_info *info)
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  {
  	struct pmagbbfb_par *par = info->par;
  
  	info->var.xres = ((sfb_read(par, SFB_REG_VID_HOR) >>
  			   SFB_VID_HOR_PIX_SHIFT) & SFB_VID_HOR_PIX_MASK) * 4;
  	info->var.xres_virtual = info->var.xres;
  	info->var.yres = (sfb_read(par, SFB_REG_VID_VER) >>
  			  SFB_VID_VER_SL_SHIFT) & SFB_VID_VER_SL_MASK;
  	info->var.yres_virtual = info->var.yres;
  	info->var.left_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
  				  SFB_VID_HOR_BP_SHIFT) &
  				 SFB_VID_HOR_BP_MASK) * 4;
  	info->var.right_margin = ((sfb_read(par, SFB_REG_VID_HOR) >>
  				   SFB_VID_HOR_FP_SHIFT) &
  				  SFB_VID_HOR_FP_MASK) * 4;
  	info->var.upper_margin = (sfb_read(par, SFB_REG_VID_VER) >>
  				  SFB_VID_VER_BP_SHIFT) & SFB_VID_VER_BP_MASK;
  	info->var.lower_margin = (sfb_read(par, SFB_REG_VID_VER) >>
  				  SFB_VID_VER_FP_SHIFT) & SFB_VID_VER_FP_MASK;
  	info->var.hsync_len = ((sfb_read(par, SFB_REG_VID_HOR) >>
  				SFB_VID_HOR_SYN_SHIFT) &
  			       SFB_VID_HOR_SYN_MASK) * 4;
  	info->var.vsync_len = (sfb_read(par, SFB_REG_VID_VER) >>
  			       SFB_VID_VER_SYN_SHIFT) & SFB_VID_VER_SYN_MASK;
  
  	info->fix.line_length = info->var.xres;
  };
  
  /*
   * Determine oscillator configuration.
   */
5b1638d94   Ralf Baechle   VIDEO: PMAGB-B: F...
169
  static void __devinit pmagbbfb_osc_setup(struct fb_info *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  {
5b1638d94   Ralf Baechle   VIDEO: PMAGB-B: F...
171
  	static unsigned int pmagbbfb_freqs[] __devinitdata = {
572c04b24   Maciej W. Rozycki   [PATCH] pmagb-b-f...
172
  		130808, 119843, 104000, 92980, 74370, 72800,
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
173
174
175
  		69197, 66000, 65000, 50350, 36000, 32000, 25175
  	};
  	struct pmagbbfb_par *par = info->par;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
176
  	struct tc_bus *tbus = to_tc_dev(info->device)->bus;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
177
  	u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
178
  	u32 freq0, freq1, freqtc = tc_get_speed(tbus) / 250;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  	int i, j;
  
  	gp0_write(par, 0);				/* select Osc0 */
  	for (j = 0; j < 16; j++) {
  		mb();
  		sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
  		mb();
  		for (i = 0; i < 100; i++) {	/* nominally max. 20.5us */
  			if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
  				break;
  			udelay(1);
  		}
  		count0 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
  	}
  
  	gp0_write(par, 1);				/* select Osc1 */
  	for (j = 0; j < 16; j++) {
  		mb();
  		sfb_write(par, SFB_REG_TCCLK_COUNT, 0);
  
  		for (i = 0; i < 100; i++) {	/* nominally max. 20.5us */
  			if (sfb_read(par, SFB_REG_TCCLK_COUNT) == 0)
  				break;
  			udelay(1);
  		}
  		count1 += sfb_read(par, SFB_REG_VIDCLK_COUNT);
  	}
  
  	freq0 = (freqtc * count0 + counttc / 2) / counttc;
  	par->osc0 = freq0;
  	if (freq0 >= pmagbbfb_freqs[0] - (pmagbbfb_freqs[0] + 32) / 64 &&
  	    freq0 <= pmagbbfb_freqs[0] + (pmagbbfb_freqs[0] + 32) / 64)
  		par->osc0 = pmagbbfb_freqs[0];
  
  	freq1 = (par->osc0 * count1 + count0 / 2) / count0;
  	par->osc1 = freq1;
d1ae418ee   Tobias Klauser   [PATCH] drivers/v...
215
  	for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++)
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  		if (freq1 >= pmagbbfb_freqs[i] -
  			     (pmagbbfb_freqs[i] + 128) / 256 &&
  		    freq1 <= pmagbbfb_freqs[i] +
  			     (pmagbbfb_freqs[i] + 128) / 256) {
  			par->osc1 = pmagbbfb_freqs[i];
  			break;
  		}
  
  	if (par->osc0 - par->osc1 <= (par->osc0 + par->osc1 + 256) / 512 ||
  	    par->osc1 - par->osc0 <= (par->osc0 + par->osc1 + 256) / 512)
  		par->osc1 = 0;
  
  	gp0_write(par, par->osc1 != 0);			/* reselect OscX */
  
  	info->var.pixclock = par->osc1 ?
  			     (1000000000 + par->osc1 / 2) / par->osc1 :
  			     (1000000000 + par->osc0 / 2) / par->osc0;
  };
5b1638d94   Ralf Baechle   VIDEO: PMAGB-B: F...
234
  static int __devinit pmagbbfb_probe(struct device *dev)
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
235
  {
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
236
237
  	struct tc_dev *tdev = to_tc_dev(dev);
  	resource_size_t start, len;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
238
239
  	struct fb_info *info;
  	struct pmagbbfb_par *par;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
240
  	char freq0[12], freq1[12];
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
241
  	u32 vid_base;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
242
  	int err;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
243

9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
244
  	info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
245
  	if (!info) {
7ad33e748   Kay Sievers   video: struct dev...
246
247
  		printk(KERN_ERR "%s: Cannot allocate memory
  ", dev_name(dev));
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
248
  		return -ENOMEM;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
249
  	}
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
250
251
  
  	par = info->par;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
252
  	dev_set_drvdata(dev, info);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
253

840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
254
255
256
  	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
  		printk(KERN_ERR "%s: Cannot allocate color map
  ",
7ad33e748   Kay Sievers   video: struct dev...
257
  		       dev_name(dev));
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
258
  		err = -ENOMEM;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
259
  		goto err_alloc;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
260
  	}
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
261

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
  	info->fbops = &pmagbbfb_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	info->fix = pmagbbfb_fix;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
264
  	info->var = pmagbbfb_defined;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
  	info->flags = FBINFO_DEFAULT;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
266
267
268
  	/* Request the I/O MEM resource.  */
  	start = tdev->resource.start;
  	len = tdev->resource.end - start + 1;
7ad33e748   Kay Sievers   video: struct dev...
269
270
271
272
  	if (!request_mem_region(start, len, dev_name(dev))) {
  		printk(KERN_ERR "%s: Cannot reserve FB region
  ",
  		       dev_name(dev));
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
273
  		err = -EBUSY;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
274
  		goto err_cmap;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
275
  	}
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
276

7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
277
  	/* MMIO mapping setup.  */
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
278
  	info->fix.mmio_start = start;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
279
  	par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
280
  	if (!par->mmio) {
7ad33e748   Kay Sievers   video: struct dev...
281
282
  		printk(KERN_ERR "%s: Cannot map MMIO
  ", dev_name(dev));
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
283
  		err = -ENOMEM;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
284
  		goto err_resource;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
285
  	}
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
286
287
288
289
  	par->sfb = par->mmio + PMAGB_B_SFB;
  	par->dac = par->mmio + PMAGB_B_BT459;
  
  	/* Frame buffer mapping setup.  */
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
290
  	info->fix.smem_start = start + PMAGB_B_FBMEM;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
291
  	par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
292
  	if (!par->smem) {
7ad33e748   Kay Sievers   video: struct dev...
293
294
  		printk(KERN_ERR "%s: Cannot map FB
  ", dev_name(dev));
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
295
  		err = -ENOMEM;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
296
  		goto err_mmio_map;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
297
  	}
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
298
299
300
301
302
303
304
  	vid_base = sfb_read(par, SFB_REG_VID_BASE);
  	info->screen_base = (void __iomem *)par->smem + vid_base * 0x1000;
  	info->screen_size = info->fix.smem_len - 2 * vid_base * 0x1000;
  
  	pmagbbfb_erase_cursor(info);
  	pmagbbfb_screen_setup(info);
  	pmagbbfb_osc_setup(info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305

840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
306
307
308
309
  	err = register_framebuffer(info);
  	if (err < 0) {
  		printk(KERN_ERR "%s: Cannot register framebuffer
  ",
7ad33e748   Kay Sievers   video: struct dev...
310
  		       dev_name(dev));
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
311
  		goto err_smem_map;
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
312
  	}
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
313

9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
314
  	get_device(dev);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
315
316
317
318
  	snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
  		 par->osc0 / 1000, par->osc0 % 1000);
  	snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
  		 par->osc1 / 1000, par->osc1 % 1000);
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
319
320
  	pr_info("fb%d: %s frame buffer device at %s
  ",
7ad33e748   Kay Sievers   video: struct dev...
321
  		info->node, info->fix.id, dev_name(dev));
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
322
323
324
325
  	pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected
  ",
  		info->node, freq0, par->osc1 ? freq1 : "disabled",
  		par->osc1 != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  	return 0;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
327
328
329
330
331
332
333
  
  
  err_smem_map:
  	iounmap(par->smem);
  
  err_mmio_map:
  	iounmap(par->mmio);
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
334
335
  err_resource:
  	release_mem_region(start, len);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
336
337
338
339
  err_cmap:
  	fb_dealloc_cmap(&info->cmap);
  
  err_alloc:
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
340
  	framebuffer_release(info);
840bc9b09   Maciej W. Rozycki   pmagb-b-fb: impro...
341
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
  }
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
343
  static int __exit pmagbbfb_remove(struct device *dev)
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
344
  {
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
345
346
  	struct tc_dev *tdev = to_tc_dev(dev);
  	struct fb_info *info = dev_get_drvdata(dev);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
347
  	struct pmagbbfb_par *par = info->par;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
348
  	resource_size_t start, len;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
349

9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
350
  	put_device(dev);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
351
352
353
  	unregister_framebuffer(info);
  	iounmap(par->smem);
  	iounmap(par->mmio);
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
354
355
356
  	start = tdev->resource.start;
  	len = tdev->resource.end - start + 1;
  	release_mem_region(start, len);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
357
  	fb_dealloc_cmap(&info->cmap);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
358
  	framebuffer_release(info);
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
359
  	return 0;
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
360
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361

7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
362
363
  
  /*
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
364
   * Initialize the framebuffer.
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
365
   */
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  static const struct tc_device_id pmagbbfb_tc_table[] = {
  	{ "DEC     ", "PMAGB-BA" },
  	{ }
  };
  MODULE_DEVICE_TABLE(tc, pmagbbfb_tc_table);
  
  static struct tc_driver pmagbbfb_driver = {
  	.id_table	= pmagbbfb_tc_table,
  	.driver		= {
  		.name	= "pmagbbfb",
  		.bus	= &tc_bus_type,
  		.probe	= pmagbbfb_probe,
  		.remove	= __exit_p(pmagbbfb_remove),
  	},
  };
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
381
  static int __init pmagbbfb_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  {
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
383
  #ifndef MODULE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  	if (fb_get_options("pmagbbfb", NULL))
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
385
  		return -ENXIO;
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
386
387
  #endif
  	return tc_register_driver(&pmagbbfb_driver);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
388
389
390
391
  }
  
  static void __exit pmagbbfb_exit(void)
  {
9084b0058   Maciej W. Rozycki   [TC] pmagb-b-fb: ...
392
  	tc_unregister_driver(&pmagbbfb_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  }
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
394

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  module_init(pmagbbfb_init);
7901c7998   Ralf Baechle   [PATCH] DEC PMAGB...
396
  module_exit(pmagbbfb_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  MODULE_LICENSE("GPL");