Blame view

drivers/video/ps3fb.c 33.1 KB
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /*
   *  linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device
   *
   *	Copyright (C) 2006 Sony Computer Entertainment Inc.
   *	Copyright 2006, 2007 Sony Corporation
   *
   *  This file is based on :
   *
   *  linux/drivers/video/vfb.c -- Virtual frame buffer device
   *
   *	Copyright (C) 2002 James Simmons
   *
   *	Copyright (C) 1997 Geert Uytterhoeven
   *
   *  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.
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/string.h>
  #include <linux/mm.h>
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
25
  #include <linux/interrupt.h>
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
26
27
  #include <linux/console.h>
  #include <linux/ioctl.h>
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
28
29
  #include <linux/kthread.h>
  #include <linux/freezer.h>
84902b7af   Krzysztof Helt   fbdev: change asm...
30
  #include <linux/uaccess.h>
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
31
32
  #include <linux/fb.h>
  #include <linux/init.h>
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
33
34
  
  #include <asm/abs_addr.h>
9413c8836   Geert Uytterhoeven   powerpc/cell: Mov...
35
  #include <asm/cell-regs.h>
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
36
37
38
39
  #include <asm/lv1call.h>
  #include <asm/ps3av.h>
  #include <asm/ps3fb.h>
  #include <asm/ps3.h>
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
40
  #include <asm/ps3gpu.h>
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
41

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
42
43
  
  #define DEVICE_NAME		"ps3fb"
9ac67a358   Geert Uytterhoeven   ps3fb: Update for...
44
45
  #define GPU_CMD_BUF_SIZE			(2 * 1024 * 1024)
  #define GPU_FB_START				(64 * 1024)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
46
  #define GPU_IOIF				(0x0d000000UL)
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
47
  #define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
48
  #define GPU_MAX_LINE_LENGTH			(65536 - 64)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
49

310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  #define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */
  #define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */
  #define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */
  #define GPU_INTR_STATUS_FLIP_1			4	/* flip head B */
  #define GPU_INTR_STATUS_QUEUE_0			5	/* queue head A */
  #define GPU_INTR_STATUS_QUEUE_1			6	/* queue head B */
  
  #define GPU_DRIVER_INFO_VERSION			0x211
  
  /* gpu internals */
  struct display_head {
  	u64 be_time_stamp;
  	u32 status;
  	u32 offset;
  	u32 res1;
  	u32 res2;
  	u32 field;
  	u32 reserved1;
  
  	u64 res3;
  	u32 raster;
  
  	u64 vblank_count;
  	u32 field_vsync;
  	u32 reserved2;
  };
  
  struct gpu_irq {
  	u32 irq_outlet;
  	u32 status;
  	u32 mask;
  	u32 video_cause;
  	u32 graph_cause;
  	u32 user_cause;
  
  	u32 res1;
  	u64 res2;
  
  	u32 reserved[4];
  };
  
  struct gpu_driver_info {
  	u32 version_driver;
  	u32 version_gpu;
  	u32 memory_size;
  	u32 hardware_channel;
  
  	u32 nvcore_frequency;
  	u32 memory_frequency;
  
  	u32 reserved[1063];
  	struct display_head display_head[8];
  	struct gpu_irq irq;
  };
  
  struct ps3fb_priv {
  	unsigned int irq_no;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
107
108
  
  	u64 context_handle, memory_handle;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
109
  	struct gpu_driver_info *dinfo;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
110
111
112
  
  	u64 vblank_count;	/* frame count */
  	wait_queue_head_t wait_vsync;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
113
114
115
  	atomic_t ext_flip;	/* on/off flip with vsync */
  	atomic_t f_count;	/* fb_open count */
  	int is_blanked;
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
116
117
  	int is_kicked;
  	struct task_struct *task;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
118
119
  };
  static struct ps3fb_priv ps3fb;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
120
121
122
  struct ps3fb_par {
  	u32 pseudo_palette[16];
  	int mode_id, new_mode_id;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
123
  	unsigned int num_frames;	/* num of frame buffers */
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
124
125
  	unsigned int width;
  	unsigned int height;
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
126
127
128
  	unsigned int ddr_line_length;
  	unsigned int ddr_frame_size;
  	unsigned int xdr_frame_size;
7974f72a2   Geert Uytterhoeven   ps3fb: make frame...
129
130
131
  	unsigned int full_offset;	/* start of fullscreen DDR fb */
  	unsigned int fb_offset;		/* start of actual DDR fb */
  	unsigned int pan_offset;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
132
  };
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
133

34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
134
  #define FIRST_NATIVE_MODE_INDEX	10
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
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
  static const struct fb_videomode ps3fb_modedb[] = {
      /* 60 Hz broadcast modes (modes "1" to "5") */
      {
          /* 480i */
          "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6,
          FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      },    {
          /* 480p */
          "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6,
          FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },    {
          /* 720p */
          "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5,
          FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },    {
          /* 1080i */
          "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5,
          FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      },    {
          /* 1080p */
          "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5,
          FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },
  
      /* 50 Hz broadcast modes (modes "6" to "10") */
      {
          /* 576i */
          "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5,
          FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      },    {
          /* 576p */
          "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5,
          FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },    {
          /* 720p */
          "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
          FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },    {
a782eed65   Geoff Levand   ps3fb: fix modedb...
173
          /* 1080i */
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
174
175
176
177
178
179
180
          "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
          FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      },    {
          /* 1080p */
          "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5,
          FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
181
      [FIRST_NATIVE_MODE_INDEX] =
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
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
216
217
218
219
      /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
      {
  	/* 480if */
  	"480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6,
  	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      }, {
  	/* 480pf */
  	"480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6,
  	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      }, {
  	/* 720pf */
  	"720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      }, {
  	/* 1080if */
  	"1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      }, {
  	/* 1080pf */
  	"1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      },
  
      /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */
      {
  	/* 576if */
  	"576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      }, {
  	/* 576pf */
  	"576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      }, {
  	/* 720pf */
  	"720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
      }, {
  	/* 1080if */
a782eed65   Geoff Levand   ps3fb: fix modedb...
220
  	"1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
221
222
223
224
225
  	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
      }, {
  	/* 1080pf */
  	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
  	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
      },
  
      /* VESA modes (modes "11" to "13") */
      {
  	/* WXGA */
  	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
  	0, FB_VMODE_NONINTERLACED,
  	FB_MODE_IS_VESA
      }, {
  	/* SXGA */
  	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
  	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
  	FB_MODE_IS_VESA
      }, {
  	/* WUXGA */
  	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
  	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
  	FB_MODE_IS_VESA
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
244
245
246
247
248
249
      }
  };
  
  
  #define HEAD_A
  #define HEAD_B
2ce32e15a   Geert Uytterhoeven   ps3fb: fix possib...
250
  #define BPP		4			/* number of bytes per pixel */
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
251

bd685ac8e   Geert Uytterhoeven   ps3fb: kill super...
252
  static int ps3fb_mode;
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
253
  module_param(ps3fb_mode, int, 0);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
254

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
255
  static char *mode_option __devinitdata;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
256

633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
257
258
259
  static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
  			  const struct fb_var_screeninfo *var)
  {
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
260
261
262
263
264
265
266
267
  	long xres, yres, left_margin, right_margin, upper_margin, lower_margin;
  	long dx, dy;
  
  	/* maximum values */
  	if (var->xres > vmode->xres || var->yres > vmode->yres ||
  	    var->pixclock > vmode->pixclock ||
  	    var->hsync_len > vmode->hsync_len ||
  	    var->vsync_len > vmode->vsync_len)
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
268
  		return -1;
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
269
270
  	/* progressive/interlaced must match */
  	if ((var->vmode & FB_VMODE_MASK) != vmode->vmode)
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
271
  		return -1;
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  	/* minimum resolution */
  	xres = max(var->xres, 1U);
  	yres = max(var->yres, 1U);
  
  	/* minimum margins */
  	left_margin = max(var->left_margin, vmode->left_margin);
  	right_margin = max(var->right_margin, vmode->right_margin);
  	upper_margin = max(var->upper_margin, vmode->upper_margin);
  	lower_margin = max(var->lower_margin, vmode->lower_margin);
  
  	/* resolution + margins may not exceed native parameters */
  	dx = ((long)vmode->left_margin + (long)vmode->xres +
  	      (long)vmode->right_margin) -
  	     (left_margin + xres + right_margin);
  	if (dx < 0)
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
287
  		return -1;
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
288
289
290
291
292
293
294
295
296
297
298
299
  	dy = ((long)vmode->upper_margin + (long)vmode->yres +
  	      (long)vmode->lower_margin) -
  	     (upper_margin + yres + lower_margin);
  	if (dy < 0)
  		return -1;
  
  	/* exact match */
  	if (!dx && !dy)
  		return 0;
  
  	/* resolution difference */
  	return (vmode->xres - xres) * (vmode->yres - yres);
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
300
  }
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id)
  {
  	return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1];
  }
  
  static const struct fb_videomode *ps3fb_vmode(int id)
  {
  	u32 mode = id & PS3AV_MODE_MASK;
  
  	if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA)
  		return NULL;
  
  	if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) {
  		/* Non-fullscreen broadcast mode */
  		return &ps3fb_modedb[mode - 1];
  	}
  
  	return ps3fb_native_vmode(mode);
  }
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
320
  static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var,
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
321
  				    u32 *ddr_line_length, u32 *xdr_line_length)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
322
  {
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
323
324
  	unsigned int id, best_id;
  	int diff, best_diff;
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
325
  	const struct fb_videomode *vmode;
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
326
  	long gap;
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
327

a3665366b   Geert Uytterhoeven   ps3fb: round up v...
328
329
330
331
332
333
  	best_id = 0;
  	best_diff = INT_MAX;
  	pr_debug("%s: wanted %u [%u] %u x %u [%u] %u
  ", __func__,
  		 var->left_margin, var->xres, var->right_margin,
  		 var->upper_margin, var->yres, var->lower_margin);
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
334
335
  	for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) {
  		vmode = ps3fb_native_vmode(id);
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
  		diff = ps3fb_cmp_mode(vmode, var);
  		pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d
  ",
  			 __func__, id, vmode->left_margin, vmode->xres,
  			 vmode->right_margin, vmode->upper_margin,
  			 vmode->yres, vmode->lower_margin, diff);
  		if (diff < 0)
  			continue;
  		if (diff < best_diff) {
  			best_id = id;
  			if (!diff)
  				break;
  			best_diff = diff;
  		}
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
350
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
351

a3665366b   Geert Uytterhoeven   ps3fb: round up v...
352
353
354
355
356
357
358
359
  	if (!best_id) {
  		pr_debug("%s: no suitable mode found
  ", __func__);
  		return 0;
  	}
  
  	id = best_id;
  	vmode = ps3fb_native_vmode(id);
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
360

34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
361
  	*ddr_line_length = vmode->xres * BPP;
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
362

a3665366b   Geert Uytterhoeven   ps3fb: round up v...
363
364
  	/* minimum resolution */
  	if (!var->xres)
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
365
  		var->xres = 1;
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
366
  	if (!var->yres)
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
367
  		var->yres = 1;
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  
  	/* minimum virtual resolution */
  	if (var->xres_virtual < var->xres)
  		var->xres_virtual = var->xres;
  	if (var->yres_virtual < var->yres)
  		var->yres_virtual = var->yres;
  
  	/* minimum margins */
  	if (var->left_margin < vmode->left_margin)
  		var->left_margin = vmode->left_margin;
  	if (var->right_margin < vmode->right_margin)
  		var->right_margin = vmode->right_margin;
  	if (var->upper_margin < vmode->upper_margin)
  		var->upper_margin = vmode->upper_margin;
  	if (var->lower_margin < vmode->lower_margin)
  		var->lower_margin = vmode->lower_margin;
  
  	/* extra margins */
  	gap = ((long)vmode->left_margin + (long)vmode->xres +
  	       (long)vmode->right_margin) -
  	      ((long)var->left_margin + (long)var->xres +
  	       (long)var->right_margin);
  	if (gap > 0) {
  		var->left_margin += gap/2;
  		var->right_margin += (gap+1)/2;
  		pr_debug("%s: rounded up H to %u [%u] %u
  ", __func__,
  			 var->left_margin, var->xres, var->right_margin);
  	}
  
  	gap = ((long)vmode->upper_margin + (long)vmode->yres +
  	       (long)vmode->lower_margin) -
  	      ((long)var->upper_margin + (long)var->yres +
  	       (long)var->lower_margin);
  	if (gap > 0) {
  		var->upper_margin += gap/2;
  		var->lower_margin += (gap+1)/2;
  		pr_debug("%s: rounded up V to %u [%u] %u
  ", __func__,
  			 var->upper_margin, var->yres, var->lower_margin);
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
408
  	}
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
409

a3665366b   Geert Uytterhoeven   ps3fb: round up v...
410
411
412
413
414
  	/* fixed fields */
  	var->pixclock = vmode->pixclock;
  	var->hsync_len = vmode->hsync_len;
  	var->vsync_len = vmode->vsync_len;
  	var->sync = vmode->sync;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
415
  	if (ps3_compare_firmware_version(1, 9, 0) >= 0) {
a3665366b   Geert Uytterhoeven   ps3fb: round up v...
416
  		*xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP);
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
417
418
419
420
  		if (*xdr_line_length > GPU_MAX_LINE_LENGTH)
  			*xdr_line_length = GPU_MAX_LINE_LENGTH;
  	} else
  		*xdr_line_length = *ddr_line_length;
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
421
  	if (vmode->sync & FB_SYNC_BROADCAST) {
633bd111b   Geert Uytterhoeven   ps3fb: add suppor...
422
  		/* Full broadcast modes have the full mode bit set */
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
423
424
  		if (vmode->xres == var->xres && vmode->yres == var->yres)
  			id |= PS3AV_MODE_FULL;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
425
  	}
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
426
427
428
  	pr_debug("%s: mode %u
  ", __func__, id);
  	return id;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
429
  }
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
430
431
  static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
  			     u64 dst_offset, u64 src_offset, u32 width,
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
432
433
  			     u32 height, u32 dst_line_length,
  			     u32 src_line_length)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
434
  {
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
435
  	int status;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
436
437
438
439
440
  	u64 line_length;
  
  	line_length = dst_line_length;
  	if (src_line_length != dst_line_length)
  		line_length |= (u64)src_line_length << 32;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
441

9ac67a358   Geert Uytterhoeven   ps3fb: Update for...
442
  	src_offset += GPU_FB_START;
9b82f3e61   Geert Uytterhoeven   powerpc/ps3: Repl...
443
444
  
  	mutex_lock(&ps3_gpu_mutex);
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
445
446
447
448
449
  	status = lv1_gpu_fb_blit(ps3fb.context_handle, dst_offset,
  				 GPU_IOIF + src_offset,
  				 L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
  				 (width << 16) | height,
  				 line_length);
9b82f3e61   Geert Uytterhoeven   powerpc/ps3: Repl...
450
  	mutex_unlock(&ps3_gpu_mutex);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
451
  	if (status)
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
452
453
454
  		dev_err(dev, "%s: lv1_gpu_fb_blit failed: %d
  ", __func__,
  			status);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
455
  #ifdef HEAD_A
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
456
  	status = lv1_gpu_display_flip(ps3fb.context_handle, 0, frame_offset);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
457
  	if (status)
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
458
459
460
  		dev_err(dev, "%s: lv1_gpu_display_flip failed: %d
  ", __func__,
  			status);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
461
462
  #endif
  #ifdef HEAD_B
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
463
  	status = lv1_gpu_display_flip(ps3fb.context_handle, 1, frame_offset);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
464
  	if (status)
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
465
466
467
  		dev_err(dev, "%s: lv1_gpu_display_flip failed: %d
  ", __func__,
  			status);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
468
  #endif
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
469
470
471
472
473
  }
  
  static int ps3fb_sync(struct fb_info *info, u32 frame)
  {
  	struct ps3fb_par *par = info->par;
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
474
  	int error = 0;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
475
  	u64 ddr_base, xdr_base;
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
476

f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
477
478
479
480
481
482
483
  	if (frame > par->num_frames - 1) {
  		dev_dbg(info->device, "%s: invalid frame number (%u)
  ",
  			__func__, frame);
  		error = -EINVAL;
  		goto out;
  	}
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
484
485
  	xdr_base = frame * par->xdr_frame_size;
  	ddr_base = frame * par->ddr_frame_size;
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
486

61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
487
488
  	ps3fb_sync_image(info->device, ddr_base + par->full_offset,
  			 ddr_base + par->fb_offset, xdr_base + par->pan_offset,
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
489
490
  			 par->width, par->height, par->ddr_line_length,
  			 info->fix.line_length);
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
491
492
  
  out:
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
493
  	return error;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
494
  }
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
495
496
497
498
499
500
501
502
503
504
505
  static int ps3fb_open(struct fb_info *info, int user)
  {
  	atomic_inc(&ps3fb.f_count);
  	return 0;
  }
  
  static int ps3fb_release(struct fb_info *info, int user)
  {
  	if (atomic_dec_and_test(&ps3fb.f_count)) {
  		if (atomic_read(&ps3fb.ext_flip)) {
  			atomic_set(&ps3fb.ext_flip, 0);
ac751efa6   Torben Hohn   console: rename a...
506
  			if (console_trylock()) {
8dab63761   Jeremy Kerr   ps3fb: fix deadlo...
507
  				ps3fb_sync(info, 0);	/* single buffer */
ac751efa6   Torben Hohn   console: rename a...
508
  				console_unlock();
8dab63761   Jeremy Kerr   ps3fb: fix deadlo...
509
  			}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
  		}
  	}
  	return 0;
  }
  
      /*
       *  Setting the video mode has been split into two parts.
       *  First part, xxxfb_check_var, must not write anything
       *  to hardware, it should only verify and adjust var.
       *  This means it doesn't alter par but it does use hardware
       *  data from it to check this var.
       */
  
  static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  {
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
525
  	u32 xdr_line_length, ddr_line_length;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
526
  	int mode;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
527

61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
528
  	mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
529
530
  	if (!mode)
  		return -EINVAL;
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
531
  	/* Virtual screen */
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
532
  	if (var->xres_virtual > xdr_line_length / BPP) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
533
  		dev_dbg(info->device,
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
534
535
  			"Horizontal virtual screen size too large
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
536
537
  		return -EINVAL;
  	}
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
538
539
540
541
542
543
  	if (var->xoffset + var->xres > var->xres_virtual ||
  	    var->yoffset + var->yres > var->yres_virtual) {
  		dev_dbg(info->device, "panning out-of-range
  ");
  		return -EINVAL;
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
544
545
546
547
548
549
550
551
552
  
  	/* We support ARGB8888 only */
  	if (var->bits_per_pixel > 32 || var->grayscale ||
  	    var->red.offset > 16 || var->green.offset > 8 ||
  	    var->blue.offset > 0 || var->transp.offset > 24 ||
  	    var->red.length > 8 || var->green.length > 8 ||
  	    var->blue.length > 8 || var->transp.length > 8 ||
  	    var->red.msb_right || var->green.msb_right ||
  	    var->blue.msb_right || var->transp.msb_right || var->nonstd) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
553
554
  		dev_dbg(info->device, "We support ARGB8888 only
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  		return -EINVAL;
  	}
  
  	var->bits_per_pixel = 32;
  	var->red.offset = 16;
  	var->green.offset = 8;
  	var->blue.offset = 0;
  	var->transp.offset = 24;
  	var->red.length = 8;
  	var->green.length = 8;
  	var->blue.length = 8;
  	var->transp.length = 8;
  	var->red.msb_right = 0;
  	var->green.msb_right = 0;
  	var->blue.msb_right = 0;
  	var->transp.msb_right = 0;
  
  	/* Rotation is not supported */
  	if (var->rotate) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
574
575
  		dev_dbg(info->device, "Rotation is not supported
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
576
577
578
579
  		return -EINVAL;
  	}
  
  	/* Memory limit */
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
580
  	if (var->yres_virtual * xdr_line_length > info->fix.smem_len) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
581
582
  		dev_dbg(info->device, "Not enough memory
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
  		return -ENOMEM;
  	}
  
  	var->height = -1;
  	var->width = -1;
  
  	return 0;
  }
  
      /*
       * This routine actually sets the video mode.
       */
  
  static int ps3fb_set_par(struct fb_info *info)
  {
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
598
  	struct ps3fb_par *par = info->par;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
599
  	unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
7974f72a2   Geert Uytterhoeven   ps3fb: make frame...
600
  	unsigned int ddr_xoff, ddr_yoff, offset;
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
601
  	const struct fb_videomode *vmode;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
602
  	u64 dst;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
603

61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
604
  	mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
605
606
  	if (!mode)
  		return -EINVAL;
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
607
  	vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK);
c95344a55   Geert Uytterhoeven   ps3fb: Fix spurio...
608

fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
609
610
  	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
  	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
611
  	info->fix.line_length = xdr_line_length;
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
612

9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
613
614
615
  	par->ddr_line_length = ddr_line_length;
  	par->ddr_frame_size = vmode->yres * ddr_line_length;
  	par->xdr_frame_size = info->var.yres_virtual * xdr_line_length;
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
616
  	par->num_frames = info->fix.smem_len /
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
617
  			  max(par->ddr_frame_size, par->xdr_frame_size);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
618
619
  
  	/* Keep the special bits we cannot set using fb_var_screeninfo */
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
620
  	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
621

f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
622
623
  	par->width = info->var.xres;
  	par->height = info->var.yres;
d9a4ba6a2   Geert Uytterhoeven   ps3fb: open-code ...
624
625
  
  	/* Start of the virtual frame buffer (relative to fullscreen) */
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
626
627
628
  	ddr_xoff = info->var.left_margin - vmode->left_margin;
  	ddr_yoff = info->var.upper_margin - vmode->upper_margin;
  	offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP;
d9a4ba6a2   Geert Uytterhoeven   ps3fb: open-code ...
629

f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
630
631
  	par->fb_offset = GPU_ALIGN_UP(offset);
  	par->full_offset = par->fb_offset - offset;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
632
  	par->pan_offset = info->var.yoffset * xdr_line_length +
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
633
  			  info->var.xoffset * BPP;
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
634

0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
635
636
637
638
639
640
641
  	if (par->new_mode_id != par->mode_id) {
  		if (ps3av_set_video_mode(par->new_mode_id)) {
  			par->new_mode_id = par->mode_id;
  			return -EINVAL;
  		}
  		par->mode_id = par->new_mode_id;
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
642

f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
643
  	/* Clear XDR frame buffer memory */
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
644
  	memset((void __force *)info->screen_base, 0, info->fix.smem_len);
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
645
646
  
  	/* Clear DDR frame buffer memory */
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
647
  	lines = vmode->yres * par->num_frames;
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
648
649
  	if (par->full_offset)
  		lines++;
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
650
  	maxlines = info->fix.smem_len / ddr_line_length;
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
651
  	for (dst = 0; lines; dst += maxlines * ddr_line_length) {
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
652
  		unsigned int l = min(lines, maxlines);
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
653
  		ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l,
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
654
  				 ddr_line_length, ddr_line_length);
f1664ed8a   Geert Uytterhoeven   ps3fb: don't keep...
655
656
  		lines -= l;
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  	return 0;
  }
  
      /*
       *  Set a single color register. The values supplied are already
       *  rounded down to the hardware's capabilities (according to the
       *  entries in the var structure). Return != 0 for invalid regno.
       */
  
  static int ps3fb_setcolreg(unsigned int regno, unsigned int red,
  			   unsigned int green, unsigned int blue,
  			   unsigned int transp, struct fb_info *info)
  {
  	if (regno >= 16)
  		return 1;
  
  	red >>= 8;
  	green >>= 8;
  	blue >>= 8;
  	transp >>= 8;
  
  	((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 |
  					       green << 8 | blue;
  	return 0;
  }
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
682
683
684
685
686
687
688
689
690
  static int ps3fb_pan_display(struct fb_var_screeninfo *var,
  			     struct fb_info *info)
  {
  	struct ps3fb_par *par = info->par;
  
  	par->pan_offset = var->yoffset * info->fix.line_length +
  			  var->xoffset * BPP;
  	return 0;
  }
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
691
692
693
694
695
696
697
      /*
       *  As we have a virtual frame buffer, we need our own mmap function
       */
  
  static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
  {
  	unsigned long size, offset;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
698
699
700
701
702
  
  	size = vma->vm_end - vma->vm_start;
  	offset = vma->vm_pgoff << PAGE_SHIFT;
  	if (offset + size > info->fix.smem_len)
  		return -EINVAL;
2ce32e15a   Geert Uytterhoeven   ps3fb: fix possib...
703
  	offset += info->fix.smem_start;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
704
705
706
  	if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
  			    size, vma->vm_page_prot))
  		return -EAGAIN;
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
707
708
709
  	dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)
  ",
  		offset, vma->vm_start);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
710
711
712
713
714
715
716
717
718
719
  	return 0;
  }
  
      /*
       * Blank the display
       */
  
  static int ps3fb_blank(int blank, struct fb_info *info)
  {
  	int retval;
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
720
721
  	dev_dbg(info->device, "%s: blank:%d
  ", __func__, blank);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
  	switch (blank) {
  	case FB_BLANK_POWERDOWN:
  	case FB_BLANK_HSYNC_SUSPEND:
  	case FB_BLANK_VSYNC_SUSPEND:
  	case FB_BLANK_NORMAL:
  		retval = ps3av_video_mute(1);	/* mute on */
  		if (!retval)
  			ps3fb.is_blanked = 1;
  		break;
  
  	default:		/* unblank */
  		retval = ps3av_video_mute(0);	/* mute off */
  		if (!retval)
  			ps3fb.is_blanked = 0;
  		break;
  	}
  	return retval;
  }
  
  static int ps3fb_get_vblank(struct fb_vblank *vblank)
  {
3cc2c1770   Li Zefan   drivers/video/ps3...
743
  	memset(vblank, 0, sizeof(*vblank));
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
744
745
746
  	vblank->flags = FB_VBLANK_HAVE_VSYNC;
  	return 0;
  }
15e4d001e   Geert Uytterhoeven   ps3fb: make ps3fb...
747
  static int ps3fb_wait_for_vsync(u32 crtc)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
748
749
750
751
752
753
754
755
756
757
758
759
760
  {
  	int ret;
  	u64 count;
  
  	count = ps3fb.vblank_count;
  	ret = wait_event_interruptible_timeout(ps3fb.wait_vsync,
  					       count != ps3fb.vblank_count,
  					       HZ / 10);
  	if (!ret)
  		return -ETIMEDOUT;
  
  	return 0;
  }
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
761
762
763
764
765
766
767
768
769
  
      /*
       * ioctl
       */
  
  static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
  		       unsigned long arg)
  {
  	void __user *argp = (void __user *)arg;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
770
  	u32 val;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
771
772
773
774
775
776
  	int retval = -EFAULT;
  
  	switch (cmd) {
  	case FBIOGET_VBLANK:
  		{
  			struct fb_vblank vblank;
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
777
778
  			dev_dbg(info->device, "FBIOGET_VBLANK:
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
779
780
781
782
783
784
785
786
787
788
789
790
  			retval = ps3fb_get_vblank(&vblank);
  			if (retval)
  				break;
  
  			if (copy_to_user(argp, &vblank, sizeof(vblank)))
  				retval = -EFAULT;
  			break;
  		}
  
  	case FBIO_WAITFORVSYNC:
  		{
  			u32 crt;
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
791
792
  			dev_dbg(info->device, "FBIO_WAITFORVSYNC:
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
793
794
795
796
797
798
799
800
801
  			if (get_user(crt, (u32 __user *) arg))
  				break;
  
  			retval = ps3fb_wait_for_vsync(crt);
  			break;
  		}
  
  	case PS3FB_IOCTL_SETMODE:
  		{
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
802
  			struct ps3fb_par *par = info->par;
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
803
  			const struct fb_videomode *vmode;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
804
805
806
807
  			struct fb_var_screeninfo var;
  
  			if (copy_from_user(&val, argp, sizeof(val)))
  				break;
640729014   Masashi Kimoto   ps3: Make `ps3vid...
808
  			if (!(val & PS3AV_MODE_MASK)) {
ce4c371a9   Geert Uytterhoeven   ps3av: dont disti...
809
  				u32 id = ps3av_get_auto_mode();
640729014   Masashi Kimoto   ps3: Make `ps3vid...
810
811
812
  				if (id > 0)
  					val = (val & ~PS3AV_MODE_MASK) | id;
  			}
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
813
814
  			dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x
  ", val);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
815
  			retval = -EINVAL;
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
816
817
  			vmode = ps3fb_vmode(val);
  			if (vmode) {
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
818
  				var = info->var;
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
819
  				fb_videomode_to_var(&var, vmode);
ac751efa6   Torben Hohn   console: rename a...
820
  				console_lock();
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
821
822
823
  				info->flags |= FBINFO_MISC_USEREVENT;
  				/* Force, in case only special bits changed */
  				var.activate |= FB_ACTIVATE_FORCE;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
824
  				par->new_mode_id = val;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
825
826
  				retval = fb_set_var(info, &var);
  				info->flags &= ~FBINFO_MISC_USEREVENT;
ac751efa6   Torben Hohn   console: rename a...
827
  				console_unlock();
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
828
  			}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
829
830
831
832
833
  			break;
  		}
  
  	case PS3FB_IOCTL_GETMODE:
  		val = ps3av_get_mode();
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
834
835
  		dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x
  ", val);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
836
837
838
839
840
841
  		if (!copy_to_user(argp, &val, sizeof(val)))
  			retval = 0;
  		break;
  
  	case PS3FB_IOCTL_SCREENINFO:
  		{
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
842
  			struct ps3fb_par *par = info->par;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
843
  			struct ps3fb_ioctl_res res;
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
844
845
  			dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:
  ");
61e0b28e5   Geert Uytterhoeven   ps3fb: enhance ho...
846
847
848
849
  			res.xres = info->fix.line_length / BPP;
  			res.yres = info->var.yres_virtual;
  			res.xoff = (res.xres - info->var.xres) / 2;
  			res.yoff = (res.yres - info->var.yres) / 2;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
850
  			res.num_frames = par->num_frames;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
851
852
853
854
855
856
  			if (!copy_to_user(argp, &res, sizeof(res)))
  				retval = 0;
  			break;
  		}
  
  	case PS3FB_IOCTL_ON:
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
857
858
  		dev_dbg(info->device, "PS3FB_IOCTL_ON:
  ");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
859
860
861
862
863
  		atomic_inc(&ps3fb.ext_flip);
  		retval = 0;
  		break;
  
  	case PS3FB_IOCTL_OFF:
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
864
865
  		dev_dbg(info->device, "PS3FB_IOCTL_OFF:
  ");
eca28743b   Geert Uytterhoeven   ps3fb: atomic fixes
866
  		atomic_dec_if_positive(&ps3fb.ext_flip);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
867
868
869
870
871
872
  		retval = 0;
  		break;
  
  	case PS3FB_IOCTL_FSEL:
  		if (copy_from_user(&val, argp, sizeof(val)))
  			break;
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
873
874
  		dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d
  ", val);
ac751efa6   Torben Hohn   console: rename a...
875
  		console_lock();
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
876
  		retval = ps3fb_sync(info, val);
ac751efa6   Torben Hohn   console: rename a...
877
  		console_unlock();
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
878
879
880
881
882
883
884
885
886
887
888
  		break;
  
  	default:
  		retval = -ENOIOCTLCMD;
  		break;
  	}
  	return retval;
  }
  
  static int ps3fbd(void *arg)
  {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
889
  	struct fb_info *info = arg;
831441862   Rafael J. Wysocki   Freezer: make ker...
890
  	set_freezable();
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
891
892
893
894
895
  	while (!kthread_should_stop()) {
  		try_to_freeze();
  		set_current_state(TASK_INTERRUPTIBLE);
  		if (ps3fb.is_kicked) {
  			ps3fb.is_kicked = 0;
ac751efa6   Torben Hohn   console: rename a...
896
  			console_lock();
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
897
  			ps3fb_sync(info, 0);	/* single buffer */
ac751efa6   Torben Hohn   console: rename a...
898
  			console_unlock();
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
899
900
  		}
  		schedule();
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
901
902
903
904
905
906
  	}
  	return 0;
  }
  
  static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr)
  {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
907
  	struct device *dev = ptr;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
908
909
910
911
912
913
  	u64 v1;
  	int status;
  	struct display_head *head = &ps3fb.dinfo->display_head[1];
  
  	status = lv1_gpu_context_intr(ps3fb.context_handle, &v1);
  	if (status) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
914
915
916
  		dev_err(dev, "%s: lv1_gpu_context_intr failed: %d
  ", __func__,
  			status);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
917
918
919
920
921
922
  		return IRQ_NONE;
  	}
  
  	if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) {
  		/* VSYNC */
  		ps3fb.vblank_count = head->vblank_count;
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
923
924
925
926
927
  		if (ps3fb.task && !ps3fb.is_blanked &&
  		    !atomic_read(&ps3fb.ext_flip)) {
  			ps3fb.is_kicked = 1;
  			wake_up_process(ps3fb.task);
  		}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
928
929
930
931
932
  		wake_up_interruptible(&ps3fb.wait_vsync);
  	}
  
  	return IRQ_HANDLED;
  }
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
933

310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
934
935
936
  static struct fb_ops ps3fb_ops = {
  	.fb_open	= ps3fb_open,
  	.fb_release	= ps3fb_release,
92c4579db   Geert Uytterhoeven   ps3fb: use FB_SYS...
937
938
  	.fb_read        = fb_sys_read,
  	.fb_write       = fb_sys_write,
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
939
940
941
  	.fb_check_var	= ps3fb_check_var,
  	.fb_set_par	= ps3fb_set_par,
  	.fb_setcolreg	= ps3fb_setcolreg,
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
942
  	.fb_pan_display	= ps3fb_pan_display,
92c4579db   Geert Uytterhoeven   ps3fb: use FB_SYS...
943
944
945
  	.fb_fillrect	= sys_fillrect,
  	.fb_copyarea	= sys_copyarea,
  	.fb_imageblit	= sys_imageblit,
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
946
947
948
949
950
951
952
  	.fb_mmap	= ps3fb_mmap,
  	.fb_blank	= ps3fb_blank,
  	.fb_ioctl	= ps3fb_ioctl,
  	.fb_compat_ioctl = ps3fb_ioctl
  };
  
  static struct fb_fix_screeninfo ps3fb_fix __initdata = {
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
953
  	.id =		DEVICE_NAME,
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
954
955
956
957
  	.type =		FB_TYPE_PACKED_PIXELS,
  	.visual =	FB_VISUAL_TRUECOLOR,
  	.accel =	FB_ACCEL_NONE,
  };
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
958
  static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
959
960
  {
  	struct fb_info *info;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
961
  	struct ps3fb_par *par;
ca971ea39   Geert Uytterhoeven   ps3fb: Correct ha...
962
  	int retval;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
963
964
965
966
967
968
  	u64 ddr_lpar = 0;
  	u64 lpar_dma_control = 0;
  	u64 lpar_driver_info = 0;
  	u64 lpar_reports = 0;
  	u64 lpar_reports_size = 0;
  	u64 xdr_lpar;
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
969
  	struct gpu_driver_info *dinfo;
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
970
  	void *fb_start;
9f4f21b45   Geert Uytterhoeven   ps3fb: kill ps3fb...
971
  	int status;
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
972
  	struct task_struct *task;
ee592a5bd   Geert Uytterhoeven   ps3fb: video memo...
973
  	unsigned long max_ps3fb_size;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
974

9ac67a358   Geert Uytterhoeven   ps3fb: Update for...
975
976
977
978
979
  	if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) {
  		dev_err(&dev->core, "%s: Not enough video memory
  ", __func__);
  		return -ENOMEM;
  	}
ca971ea39   Geert Uytterhoeven   ps3fb: Correct ha...
980
981
  	retval = ps3_open_hv_device(dev);
  	if (retval) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
982
983
984
  		dev_err(&dev->core, "%s: ps3_open_hv_device failed
  ",
  			__func__);
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
985
986
987
988
989
  		goto err;
  	}
  
  	if (!ps3fb_mode)
  		ps3fb_mode = ps3av_get_mode();
084ffff29   Geert Uytterhoeven   ps3: use symbolic...
990
991
  	dev_dbg(&dev->core, "ps3fb_mode: %d
  ", ps3fb_mode);
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
992

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
993
994
995
  	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
  	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
  	init_waitqueue_head(&ps3fb.wait_vsync);
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
996

bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
997
  #ifdef HEAD_A
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
998
  	status = lv1_gpu_display_sync(0x0, 0, L1GPU_DISPLAY_SYNC_VSYNC);
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
999
  	if (status) {
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
1000
1001
  		dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d
  ",
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1002
  			__func__, status);
ca971ea39   Geert Uytterhoeven   ps3fb: Correct ha...
1003
1004
  		retval = -ENODEV;
  		goto err_close_device;
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1005
1006
1007
  	}
  #endif
  #ifdef HEAD_B
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
1008
  	status = lv1_gpu_display_sync(0x0, 1, L1GPU_DISPLAY_SYNC_VSYNC);
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1009
  	if (status) {
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
1010
1011
  		dev_err(&dev->core, "%s: lv1_gpu_display_sync failed: %d
  ",
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1012
  			__func__, status);
ca971ea39   Geert Uytterhoeven   ps3fb: Correct ha...
1013
1014
  		retval = -ENODEV;
  		goto err_close_device;
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1015
1016
  	}
  #endif
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1017

ee592a5bd   Geert Uytterhoeven   ps3fb: video memo...
1018
1019
1020
1021
1022
1023
1024
  	max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF;
  	if (ps3fb_videomemory.size > max_ps3fb_size) {
  		dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes
  ",
  			 max_ps3fb_size);
  		ps3fb_videomemory.size = max_ps3fb_size;
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1025
  	/* get gpu context handle */
ee592a5bd   Geert Uytterhoeven   ps3fb: video memo...
1026
  	status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0,
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1027
1028
  					 &ps3fb.memory_handle, &ddr_lpar);
  	if (status) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1029
1030
1031
  		dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d
  ",
  			__func__, status);
ca971ea39   Geert Uytterhoeven   ps3fb: Correct ha...
1032
  		goto err_close_device;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1033
  	}
5d9ee3ff3   Stephen Rothwell   powerpc/ps3: prin...
1034
1035
  	dev_dbg(&dev->core, "ddr:lpar:0x%llx
  ", ddr_lpar);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1036
1037
1038
1039
1040
1041
  
  	status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0,
  					  &ps3fb.context_handle,
  					  &lpar_dma_control, &lpar_driver_info,
  					  &lpar_reports, &lpar_reports_size);
  	if (status) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1042
  		dev_err(&dev->core,
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
1043
1044
  			"%s: lv1_gpu_context_allocate failed: %d
  ", __func__,
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1045
  			status);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1046
1047
1048
1049
  		goto err_gpu_memory_free;
  	}
  
  	/* vsync interrupt */
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1050
1051
  	dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
  	if (!dinfo) {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1052
1053
  		dev_err(&dev->core, "%s: ioremap failed
  ", __func__);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1054
1055
  		goto err_gpu_context_free;
  	}
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
  	ps3fb.dinfo = dinfo;
  	dev_dbg(&dev->core, "version_driver:%x
  ", dinfo->version_driver);
  	dev_dbg(&dev->core, "irq outlet:%x
  ", dinfo->irq.irq_outlet);
  	dev_dbg(&dev->core, "version_gpu: %x memory_size: %x ch: %x "
  		"core_freq: %d mem_freq:%d
  ", dinfo->version_gpu,
  		dinfo->memory_size, dinfo->hardware_channel,
  		dinfo->nvcore_frequency/1000000,
  		dinfo->memory_frequency/1000000);
  
  	if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) {
  		dev_err(&dev->core, "%s: version_driver err:%x
  ", __func__,
  			dinfo->version_driver);
  		retval = -EINVAL;
  		goto err_iounmap_dinfo;
  	}
  
  	retval = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet,
  				    &ps3fb.irq_no);
  	if (retval) {
  		dev_err(&dev->core, "%s: ps3_alloc_irq failed %d
  ", __func__,
  			retval);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1082
  		goto err_iounmap_dinfo;
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1083
1084
1085
  	}
  
  	retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt,
f8798ccbe   Yong Zhang   video: irq: Remov...
1086
  			     0, DEVICE_NAME, &dev->core);
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1087
1088
1089
1090
1091
1092
1093
1094
1095
  	if (retval) {
  		dev_err(&dev->core, "%s: request_irq failed %d
  ", __func__,
  			retval);
  		goto err_destroy_plug;
  	}
  
  	dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) |
  			  (1 << GPU_INTR_STATUS_FLIP_1);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1096

2ce32e15a   Geert Uytterhoeven   ps3fb: fix possib...
1097
  	/* Clear memory to prevent kernel info leakage into userspace */
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1098
  	memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size);
2ce32e15a   Geert Uytterhoeven   ps3fb: fix possib...
1099

a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1100
  	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1101
1102
  
  	status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF,
e78d0c5c1   Geert Uytterhoeven   ps3fb: GPU memory...
1103
1104
1105
  				       xdr_lpar, ps3fb_videomemory.size,
  				       CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
  				       CBE_IOPTE_M);
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  	if (status) {
  		dev_err(&dev->core, "%s: lv1_gpu_context_iomap failed: %d
  ",
  			__func__, status);
  		retval =  -ENXIO;
  		goto err_free_irq;
  	}
  
  	dev_dbg(&dev->core, "video:%p ioif:%lx lpar:%llx size:%lx
  ",
  		ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
  		ps3fb_videomemory.size);
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
1118
1119
  	status = lv1_gpu_fb_setup(ps3fb.context_handle, xdr_lpar,
  				  GPU_CMD_BUF_SIZE, GPU_IOIF);
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1120
  	if (status) {
d3352c9f1   Geert Uytterhoeven   ps3fb/vram: Extra...
1121
1122
  		dev_err(&dev->core, "%s: lv1_gpu_fb_setup failed: %d
  ",
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1123
1124
  			__func__, status);
  		retval = -ENXIO;
e78d0c5c1   Geert Uytterhoeven   ps3fb: GPU memory...
1125
  		goto err_context_unmap;
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1126
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1127

0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
1128
  	info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1129
  	if (!info)
c204ff655   Geert Uytterhoeven   ps3fb: Tear down ...
1130
  		goto err_context_fb_close;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1131

0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
1132
1133
1134
  	par = info->par;
  	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */
  	par->new_mode_id = ps3fb_mode;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
1135
  	par->num_frames = 1;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1136
  	info->fbops = &ps3fb_ops;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1137
  	info->fix = ps3fb_fix;
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
  
  	/*
  	 * The GPU command buffer is at the start of video memory
  	 * As we don't use the full command buffer, we can put the actual
  	 * frame buffer at offset GPU_FB_START and save some precious XDR
  	 * memory
  	 */
  	fb_start = ps3fb_videomemory.address + GPU_FB_START;
  	info->screen_base = (char __force __iomem *)fb_start;
  	info->fix.smem_start = virt_to_abs(fb_start);
  	info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START;
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
1149
  	info->pseudo_palette = par->pseudo_palette;
fc7028b74   Geert Uytterhoeven   ps3fb: add virtua...
1150
1151
  	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
  		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1152
1153
1154
1155
1156
1157
  
  	retval = fb_alloc_cmap(&info->cmap, 256, 0);
  	if (retval < 0)
  		goto err_framebuffer_release;
  
  	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
0333d8350   Geert Uytterhoeven   ps3fb: use fb_inf...
1158
  			  ARRAY_SIZE(ps3fb_modedb),
34c422fb2   Geert Uytterhoeven   ps3fb: reorganize...
1159
  			  ps3fb_vmode(par->new_mode_id), 32)) {
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
  		retval = -EINVAL;
  		goto err_fb_dealloc;
  	}
  
  	fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb),
  				 &info->modelist);
  
  	retval = register_framebuffer(info);
  	if (retval < 0)
  		goto err_fb_dealloc;
cd4a157d7   Geert Uytterhoeven   ps3fb: Use ps3_sy...
1170
  	ps3_system_bus_set_drvdata(dev, info);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1171

a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1172
1173
  	dev_info(info->device, "%s %s, using %u KiB of video memory
  ",
7ad33e748   Kay Sievers   video: struct dev...
1174
  		 dev_driver_string(info->dev), dev_name(info->dev),
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1175
  		 info->fix.smem_len >> 10);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1176

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1177
  	task = kthread_run(ps3fbd, info, DEVICE_NAME);
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
1178
1179
1180
1181
1182
1183
  	if (IS_ERR(task)) {
  		retval = PTR_ERR(task);
  		goto err_unregister_framebuffer;
  	}
  
  	ps3fb.task = task;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1184
  	return 0;
1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
1185
1186
  err_unregister_framebuffer:
  	unregister_framebuffer(info);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1187
1188
1189
1190
  err_fb_dealloc:
  	fb_dealloc_cmap(&info->cmap);
  err_framebuffer_release:
  	framebuffer_release(info);
c204ff655   Geert Uytterhoeven   ps3fb: Tear down ...
1191
1192
  err_context_fb_close:
  	lv1_gpu_fb_close(ps3fb.context_handle);
e78d0c5c1   Geert Uytterhoeven   ps3fb: GPU memory...
1193
1194
1195
  err_context_unmap:
  	lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
  			      ps3fb_videomemory.size, CBE_IOPTE_M);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1196
  err_free_irq:
fcbe6e970   Geoff Levand   ps3fb: Fix ps3fb ...
1197
  	free_irq(ps3fb.irq_no, &dev->core);
bb94f077e   Geert Uytterhoeven   ps3fb: Inline fun...
1198
  err_destroy_plug:
dc4f60c25   Geoff Levand   [POWERPC] PS3: In...
1199
  	ps3_irq_plug_destroy(ps3fb.irq_no);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1200
  err_iounmap_dinfo:
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1201
  	iounmap((u8 __force __iomem *)ps3fb.dinfo);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1202
1203
1204
1205
  err_gpu_context_free:
  	lv1_gpu_context_free(ps3fb.context_handle);
  err_gpu_memory_free:
  	lv1_gpu_memory_free(ps3fb.memory_handle);
ca971ea39   Geert Uytterhoeven   ps3fb: Correct ha...
1206
1207
  err_close_device:
  	ps3_close_hv_device(dev);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1208
1209
1210
  err:
  	return retval;
  }
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1211
  static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1212
  {
cd4a157d7   Geert Uytterhoeven   ps3fb: Use ps3_sy...
1213
  	struct fb_info *info = ps3_system_bus_get_drvdata(dev);
e78d0c5c1   Geert Uytterhoeven   ps3fb: GPU memory...
1214
  	u64 xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1215

535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1216
1217
  	dev_dbg(&dev->core, " -> %s:%d
  ", __func__, __LINE__);
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1218

9b82f3e61   Geert Uytterhoeven   powerpc/ps3: Repl...
1219
  	atomic_inc(&ps3fb.ext_flip);	/* flip off */
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1220
  	ps3fb.dinfo->irq.mask = 0;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1221

1c0c84611   Geert Uytterhoeven   ps3fb: thread upd...
1222
1223
1224
1225
1226
  	if (ps3fb.task) {
  		struct task_struct *task = ps3fb.task;
  		ps3fb.task = NULL;
  		kthread_stop(task);
  	}
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1227
  	if (ps3fb.irq_no) {
fcbe6e970   Geoff Levand   ps3fb: Fix ps3fb ...
1228
  		free_irq(ps3fb.irq_no, &dev->core);
dc4f60c25   Geoff Levand   [POWERPC] PS3: In...
1229
  		ps3_irq_plug_destroy(ps3fb.irq_no);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1230
  	}
ba21611c9   Jeremy Kerr   ps3fb: prevent us...
1231
1232
1233
1234
  	if (info) {
  		unregister_framebuffer(info);
  		fb_dealloc_cmap(&info->cmap);
  		framebuffer_release(info);
cd4a157d7   Geert Uytterhoeven   ps3fb: Use ps3_sy...
1235
  		ps3_system_bus_set_drvdata(dev, NULL);
ba21611c9   Jeremy Kerr   ps3fb: prevent us...
1236
  	}
a286408c7   Geert Uytterhoeven   ps3fb: cleanup sweep
1237
  	iounmap((u8 __force __iomem *)ps3fb.dinfo);
c204ff655   Geert Uytterhoeven   ps3fb: Tear down ...
1238
  	lv1_gpu_fb_close(ps3fb.context_handle);
e78d0c5c1   Geert Uytterhoeven   ps3fb: GPU memory...
1239
1240
  	lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar,
  			      ps3fb_videomemory.size, CBE_IOPTE_M);
02aad32c3   Geert Uytterhoeven   ps3fb: Remove use...
1241
1242
  	lv1_gpu_context_free(ps3fb.context_handle);
  	lv1_gpu_memory_free(ps3fb.memory_handle);
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1243
  	ps3_close_hv_device(dev);
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1244
1245
  	dev_dbg(&dev->core, " <- %s:%d
  ", __func__, __LINE__);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1246

310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1247
1248
  	return 0;
  }
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1249
  static struct ps3_system_bus_driver ps3fb_driver = {
46d01492b   Geert Uytterhoeven   powerpc/ps3: Add ...
1250
1251
  	.match_id	= PS3_MATCH_ID_GPU,
  	.match_sub_id	= PS3_MATCH_SUB_ID_GPU_FB,
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1252
1253
1254
1255
1256
  	.core.name	= DEVICE_NAME,
  	.core.owner	= THIS_MODULE,
  	.probe		= ps3fb_probe,
  	.remove		= ps3fb_shutdown,
  	.shutdown	= ps3fb_shutdown,
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1257
  };
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1258
  static int __init ps3fb_setup(void)
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1259
  {
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1260
  	char *options;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1261

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1262
  #ifdef MODULE
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1263
  	return 0;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1264
  #endif
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1265
1266
  	if (fb_get_options(DEVICE_NAME, &options))
  		return -ENXIO;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1267

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1268
1269
  	if (!options || !*options)
  		return 0;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1270

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1271
1272
  	while (1) {
  		char *this_opt = strsep(&options, ",");
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1273

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1274
1275
1276
1277
1278
1279
1280
1281
  		if (!this_opt)
  			break;
  		if (!*this_opt)
  			continue;
  		if (!strncmp(this_opt, "mode:", 5))
  			ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0);
  		else
  			mode_option = this_opt;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1282
  	}
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1283
1284
  	return 0;
  }
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1285

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1286
1287
1288
1289
  static int __init ps3fb_init(void)
  {
  	if (!ps3fb_videomemory.address ||  ps3fb_setup())
  		return -ENXIO;
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1290

9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1291
  	return ps3_system_bus_driver_register(&ps3fb_driver);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1292
  }
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1293
1294
  static void __exit ps3fb_exit(void)
  {
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1295
1296
  	pr_debug(" -> %s:%d
  ", __func__, __LINE__);
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1297
  	ps3_system_bus_driver_unregister(&ps3fb_driver);
535da7ffe   Geert Uytterhoeven   ps3fb: convert fr...
1298
1299
  	pr_debug(" <- %s:%d
  ", __func__, __LINE__);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1300
  }
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1301
  module_init(ps3fb_init);
310d8c111   Geert Uytterhoeven   [PATCH] ps3: Virt...
1302
1303
1304
  module_exit(ps3fb_exit);
  
  MODULE_LICENSE("GPL");
9e6b99bd4   Geert Uytterhoeven   [POWERPC] PS3: Fr...
1305
1306
  MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
  MODULE_AUTHOR("Sony Computer Entertainment Inc.");
46d01492b   Geert Uytterhoeven   powerpc/ps3: Add ...
1307
  MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_FB);