Blame view

drivers/video/p9100.c 9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /* p9100.c: P9100 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
   * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
   *
   * 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
13
14
15
16
  #include <linux/delay.h>
  #include <linux/init.h>
  #include <linux/fb.h>
  #include <linux/mm.h>
6cd5a86b5   Robert Reif   sparc video: remo...
17
  #include <linux/of_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
  
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
  #include <asm/fbio.h>
  
  #include "sbuslib.h"
  
  /*
   * Local functions.
   */
  
  static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned,
  			   unsigned, struct fb_info *);
  static int p9100_blank(int, struct fb_info *);
216d526c8   Christoph Hellwig   [PATCH] fbdev: Sa...
31
  static int p9100_mmap(struct fb_info *, struct vm_area_struct *);
67a6680d6   Christoph Hellwig   [PATCH] fbdev: Sa...
32
  static int p9100_ioctl(struct fb_info *, unsigned int, unsigned long);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  
  /*
   *  Frame buffer operations
   */
  
  static struct fb_ops p9100_ops = {
  	.owner			= THIS_MODULE,
  	.fb_setcolreg		= p9100_setcolreg,
  	.fb_blank		= p9100_blank,
  	.fb_fillrect		= cfb_fillrect,
  	.fb_copyarea		= cfb_copyarea,
  	.fb_imageblit		= cfb_imageblit,
  	.fb_mmap		= p9100_mmap,
  	.fb_ioctl		= p9100_ioctl,
9ffb83bcc   Christoph Hellwig   [SBUSFB]: impleme...
47
48
49
  #ifdef CONFIG_COMPAT
  	.fb_compat_ioctl	= sbusfb_compat_ioctl,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  };
  
  /* P9100 control registers */
  #define P9100_SYSCTL_OFF	0x0UL
  #define P9100_VIDEOCTL_OFF	0x100UL
  #define P9100_VRAMCTL_OFF 	0x180UL
  #define P9100_RAMDAC_OFF 	0x200UL
  #define P9100_VIDEOCOPROC_OFF 	0x400UL
  
  /* P9100 command registers */
  #define P9100_CMD_OFF 0x0UL
  
  /* P9100 framebuffer memory */
  #define P9100_FB_OFF 0x0UL
  
  /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
  #define SYS_CONFIG_PIXELSIZE_SHIFT 26 
  
  #define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
  
  struct p9100_regs {
  	/* Registers for the system control */
50312ce9d   David S. Miller   [SPARC]: Convert ...
72
73
74
75
76
77
78
  	u32 sys_base;
  	u32 sys_config;
  	u32 sys_intr;
  	u32 sys_int_ena;
  	u32 sys_alt_rd;
  	u32 sys_alt_wr;
  	u32 sys_xxx[58];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
  
  	/* Registers for the video control */
50312ce9d   David S. Miller   [SPARC]: Convert ...
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  	u32 vid_base;
  	u32 vid_hcnt;
  	u32 vid_htotal;
  	u32 vid_hsync_rise;
  	u32 vid_hblank_rise;
  	u32 vid_hblank_fall;
  	u32 vid_hcnt_preload;
  	u32 vid_vcnt;
  	u32 vid_vlen;
  	u32 vid_vsync_rise;
  	u32 vid_vblank_rise;
  	u32 vid_vblank_fall;
  	u32 vid_vcnt_preload;
  	u32 vid_screenpaint_addr;
  	u32 vid_screenpaint_timectl1;
  	u32 vid_screenpaint_qsfcnt;
  	u32 vid_screenpaint_timectl2;
  	u32 vid_xxx[15];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
  
  	/* Registers for the video control */
50312ce9d   David S. Miller   [SPARC]: Convert ...
101
102
103
104
105
106
107
108
  	u32 vram_base;
  	u32 vram_memcfg;
  	u32 vram_refresh_pd;
  	u32 vram_refresh_cnt;
  	u32 vram_raslo_max;
  	u32 vram_raslo_cur;
  	u32 pwrup_cfg;
  	u32 vram_xxx[25];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
  
  	/* Registers for IBM RGB528 Palette */
50312ce9d   David S. Miller   [SPARC]: Convert ...
111
112
113
114
115
116
117
118
119
  	u32 ramdac_cmap_wridx; 
  	u32 ramdac_palette_data;
  	u32 ramdac_pixel_mask;
  	u32 ramdac_palette_rdaddr;
  	u32 ramdac_idx_lo;
  	u32 ramdac_idx_hi;
  	u32 ramdac_idx_data;
  	u32 ramdac_idx_ctl;
  	u32 ramdac_xxx[1784];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
  };
  
  struct p9100_cmd_parameng {
50312ce9d   David S. Miller   [SPARC]: Convert ...
123
124
125
  	u32 parameng_status;
  	u32 parameng_bltcmd;
  	u32 parameng_quadcmd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
132
133
  };
  
  struct p9100_par {
  	spinlock_t		lock;
  	struct p9100_regs	__iomem *regs;
  
  	u32			flags;
  #define P9100_FLAG_BLANKED	0x00000001
50312ce9d   David S. Miller   [SPARC]: Convert ...
134
  	unsigned long		which_io;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
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
169
170
171
172
173
174
175
176
177
178
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
215
  };
  
  /**
   *      p9100_setcolreg - Optional function. 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
   */
  static int p9100_setcolreg(unsigned regno,
  			   unsigned red, unsigned green, unsigned blue,
  			   unsigned transp, struct fb_info *info)
  {
  	struct p9100_par *par = (struct p9100_par *) info->par;
  	struct p9100_regs __iomem *regs = par->regs;
  	unsigned long flags;
  
  	if (regno >= 256)
  		return 1;
  
  	red >>= 8;
  	green >>= 8;
  	blue >>= 8;
  
  	spin_lock_irqsave(&par->lock, flags);
  
  	sbus_writel((regno << 16), &regs->ramdac_cmap_wridx);
  	sbus_writel((red << 16), &regs->ramdac_palette_data);
  	sbus_writel((green << 16), &regs->ramdac_palette_data);
  	sbus_writel((blue << 16), &regs->ramdac_palette_data);
  
  	spin_unlock_irqrestore(&par->lock, flags);
  
  	return 0;
  }
  
  /**
   *      p9100_blank - Optional function.  Blanks the display.
   *      @blank_mode: the blank mode we want.
   *      @info: frame buffer structure that represents a single frame buffer
   */
  static int
  p9100_blank(int blank, struct fb_info *info)
  {
  	struct p9100_par *par = (struct p9100_par *) info->par;
  	struct p9100_regs __iomem *regs = par->regs;
  	unsigned long flags;
  	u32 val;
  
  	spin_lock_irqsave(&par->lock, flags);
  
  	switch (blank) {
  	case FB_BLANK_UNBLANK: /* Unblanking */
  		val = sbus_readl(&regs->vid_screenpaint_timectl1);
  		val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
  		sbus_writel(val, &regs->vid_screenpaint_timectl1);
  		par->flags &= ~P9100_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 */
  		val = sbus_readl(&regs->vid_screenpaint_timectl1);
  		val &= ~SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
  		sbus_writel(val, &regs->vid_screenpaint_timectl1);
  		par->flags |= P9100_FLAG_BLANKED;
  		break;
  	}
  
  	spin_unlock_irqrestore(&par->lock, flags);
  
  	return 0;
  }
  
  static struct sbus_mmap_map p9100_mmap_map[] = {
  	{ CG3_MMAP_OFFSET,	0,		SBUS_MMAP_FBSIZE(1) },
  	{ 0,			0,		0		    }
  };
216d526c8   Christoph Hellwig   [PATCH] fbdev: Sa...
216
  static int p9100_mmap(struct fb_info *info, struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
  {
  	struct p9100_par *par = (struct p9100_par *)info->par;
  
  	return sbusfb_mmap_helper(p9100_mmap_map,
0d76cb260   Krzysztof Helt   p9100: use standa...
221
  				  info->fix.smem_start, info->fix.smem_len,
50312ce9d   David S. Miller   [SPARC]: Convert ...
222
  				  par->which_io, vma);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  }
67a6680d6   Christoph Hellwig   [PATCH] fbdev: Sa...
224
225
  static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
  		       unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
  	/* Make it look like a cg3. */
  	return sbusfb_ioctl_helper(cmd, arg, info,
0d76cb260   Krzysztof Helt   p9100: use standa...
229
  				   FBTYPE_SUN3COLOR, 8, info->fix.smem_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
  }
  
  /*
   *  Initialisation
   */
50312ce9d   David S. Miller   [SPARC]: Convert ...
235
  static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  {
50312ce9d   David S. Miller   [SPARC]: Convert ...
237
  	strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238
239
240
241
242
243
244
245
  
  	info->fix.type = FB_TYPE_PACKED_PIXELS;
  	info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
  
  	info->fix.line_length = linebytes;
  
  	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
  }
28541d0f1   Grant Likely   dt/video: Elimina...
246
  static int __devinit p9100_probe(struct platform_device *op)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  {
d4b8b2c2c   Anatolij Gustschin   of/video: fix bui...
248
  	struct device_node *dp = op->dev.of_node;
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
249
250
  	struct fb_info *info;
  	struct p9100_par *par;
50312ce9d   David S. Miller   [SPARC]: Convert ...
251
  	int linebytes, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
253
254
255
256
257
258
  	info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
  
  	err = -ENOMEM;
  	if (!info)
  		goto out_err;
  	par = info->par;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
260
  	spin_lock_init(&par->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
  
  	/* This is the framebuffer and the only resource apps can mmap.  */
0d76cb260   Krzysztof Helt   p9100: use standa...
263
  	info->fix.smem_start = op->resource[2].start;
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
264
  	par->which_io = op->resource[2].flags & IORESOURCE_BITS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265

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

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
271
  	linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
0d76cb260   Krzysztof Helt   p9100: use standa...
272
  	info->fix.smem_len = PAGE_ALIGN(linebytes * info->var.yres);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
274
275
276
277
  	par->regs = of_ioremap(&op->resource[0], 0,
  			       sizeof(struct p9100_regs), "p9100 regs");
  	if (!par->regs)
  		goto out_release_fb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
279
280
281
  	info->flags = FBINFO_DEFAULT;
  	info->fbops = &p9100_ops;
  	info->screen_base = of_ioremap(&op->resource[2], 0,
0d76cb260   Krzysztof Helt   p9100: use standa...
282
  				       info->fix.smem_len, "p9100 ram");
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
283
284
  	if (!info->screen_base)
  		goto out_unmap_regs;
59f7137a1   Robert Reif   sparc video: make...
285
  	p9100_blank(FB_BLANK_UNBLANK, info);
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
286
287
288
  
  	if (fb_alloc_cmap(&info->cmap, 256, 0))
  		goto out_unmap_screen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
290
291
292
293
294
295
296
297
298
  	p9100_init_fix(info, linebytes, dp);
  
  	err = register_framebuffer(info);
  	if (err < 0)
  		goto out_dealloc_cmap;
  
  	fb_set_cmap(&info->cmap, info);
  
  	dev_set_drvdata(&op->dev, info);
50312ce9d   David S. Miller   [SPARC]: Convert ...
299

194f1a68b   Robert Reif   sparc: video driv...
300
301
  	printk(KERN_INFO "%s: p9100 at %lx:%lx
  ",
50312ce9d   David S. Miller   [SPARC]: Convert ...
302
  	       dp->full_name,
0d76cb260   Krzysztof Helt   p9100: use standa...
303
  	       par->which_io, info->fix.smem_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

50312ce9d   David S. Miller   [SPARC]: Convert ...
305
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
307
308
309
310
  out_dealloc_cmap:
  	fb_dealloc_cmap(&info->cmap);
  
  out_unmap_screen:
0d76cb260   Krzysztof Helt   p9100: use standa...
311
  	of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
312
313
314
315
316
317
  
  out_unmap_regs:
  	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
  
  out_release_fb:
  	framebuffer_release(info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
319
320
  out_err:
  	return err;
50312ce9d   David S. Miller   [SPARC]: Convert ...
321
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322

2dc115813   Grant Likely   of/device: Replac...
323
  static int __devexit p9100_remove(struct platform_device *op)
50312ce9d   David S. Miller   [SPARC]: Convert ...
324
  {
c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
325
326
  	struct fb_info *info = dev_get_drvdata(&op->dev);
  	struct p9100_par *par = info->par;
50312ce9d   David S. Miller   [SPARC]: Convert ...
327

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

c7f439b99   David S. Miller   [VIDEO]: Fix OOPS...
331
  	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
0d76cb260   Krzysztof Helt   p9100: use standa...
332
  	of_iounmap(&op->resource[2], info->screen_base, info->fix.smem_len);
50312ce9d   David S. Miller   [SPARC]: Convert ...
333

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

e3a411a3d   David S. Miller   [SPARC64]: Fix of...
336
  	dev_set_drvdata(&op->dev, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
  
  	return 0;
  }
fd098316e   David S. Miller   sparc: Annotate o...
340
  static const struct of_device_id p9100_match[] = {
50312ce9d   David S. Miller   [SPARC]: Convert ...
341
342
343
344
345
346
  	{
  		.name = "p9100",
  	},
  	{},
  };
  MODULE_DEVICE_TABLE(of, p9100_match);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347

28541d0f1   Grant Likely   dt/video: Elimina...
348
  static struct platform_driver p9100_driver = {
4018294b5   Grant Likely   of: Remove duplic...
349
350
351
352
353
  	.driver = {
  		.name = "p9100",
  		.owner = THIS_MODULE,
  		.of_match_table = p9100_match,
  	},
50312ce9d   David S. Miller   [SPARC]: Convert ...
354
355
356
  	.probe		= p9100_probe,
  	.remove		= __devexit_p(p9100_remove),
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357

50312ce9d   David S. Miller   [SPARC]: Convert ...
358
359
360
361
  static int __init p9100_init(void)
  {
  	if (fb_get_options("p9100fb", NULL))
  		return -ENODEV;
28541d0f1   Grant Likely   dt/video: Elimina...
362
  	return platform_driver_register(&p9100_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  }
50312ce9d   David S. Miller   [SPARC]: Convert ...
364
  static void __exit p9100_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  {
28541d0f1   Grant Likely   dt/video: Elimina...
366
  	platform_driver_unregister(&p9100_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
  }
  
  module_init(p9100_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
  module_exit(p9100_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
  
  MODULE_DESCRIPTION("framebuffer driver for P9100 chipsets");
50312ce9d   David S. Miller   [SPARC]: Convert ...
373
374
  MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
  MODULE_VERSION("2.0");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
  MODULE_LICENSE("GPL");