Subversion Repositories Kolibri OS

Rev

Rev 1128 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1126 serge 1
/*
2
 * Copyright © 2007 David Airlie
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 * Authors:
24
 *     David Airlie
25
 */
26
    /*
27
     *  Modularization
28
     */
29
 
30
//#include 
31
//#include 
32
//#include 
33
//#include 
34
//#include 
35
//#include 
36
//#include 
37
//#include 
38
//#include 
39
//#include 
40
 
41
#include "drmP.h"
42
#include "drm.h"
43
#include "drm_crtc.h"
44
#include "drm_crtc_helper.h"
45
#include "radeon_drm.h"
46
#include "radeon.h"
47
 
48
#include 
49
#include "radeon_object.h"
50
 
51
 
52
#define FB_TYPE_PACKED_PIXELS       0   /* Packed Pixels    */
53
#define FB_VISUAL_TRUECOLOR     2   /* True color   */
54
 
55
struct fb_fix_screeninfo {
56
    char id[16];            /* identification string eg "TT Builtin" */
57
    unsigned long smem_start;   /* Start of frame buffer mem */
58
                    /* (physical address) */
59
    __u32 smem_len;         /* Length of frame buffer mem */
60
    __u32 type;         /* see FB_TYPE_*        */
61
    __u32 type_aux;         /* Interleave for interleaved Planes */
62
    __u32 visual;           /* see FB_VISUAL_*      */
63
    __u16 xpanstep;         /* zero if no hardware panning  */
64
    __u16 ypanstep;         /* zero if no hardware panning  */
65
    __u16 ywrapstep;        /* zero if no hardware ywrap    */
66
    __u32 line_length;      /* length of a line in bytes    */
67
    unsigned long mmio_start;   /* Start of Memory Mapped I/O   */
68
                    /* (physical address) */
69
    __u32 mmio_len;         /* Length of Memory Mapped I/O  */
70
    __u32 accel;            /* Indicate to driver which */
71
                    /*  specific chip/card we have  */
72
    __u16 reserved[3];      /* Reserved for future compatibility */
73
};
74
 
75
 
76
 
77
 
78
struct fb_bitfield {
79
    __u32 offset;           /* beginning of bitfield    */
80
    __u32 length;           /* length of bitfield       */
81
    __u32 msb_right;        /* != 0 : Most significant bit is */
82
                    /* right */
83
};
84
 
85
 
86
struct fb_var_screeninfo {
87
    __u32 xres;         /* visible resolution       */
88
    __u32 yres;
89
    __u32 xres_virtual;     /* virtual resolution       */
90
    __u32 yres_virtual;
91
    __u32 xoffset;          /* offset from virtual to visible */
92
    __u32 yoffset;          /* resolution           */
93
 
94
    __u32 bits_per_pixel;       /* guess what           */
95
    __u32 grayscale;        /* != 0 Graylevels instead of colors */
96
 
97
    struct fb_bitfield red;     /* bitfield in fb mem if true color, */
98
    struct fb_bitfield green;   /* else only length is significant */
99
    struct fb_bitfield blue;
100
    struct fb_bitfield transp;  /* transparency         */
101
 
102
    __u32 nonstd;           /* != 0 Non standard pixel format */
103
 
104
    __u32 activate;         /* see FB_ACTIVATE_*        */
105
 
106
    __u32 height;           /* height of picture in mm    */
107
    __u32 width;            /* width of picture in mm     */
108
 
109
    __u32 accel_flags;      /* (OBSOLETE) see fb_info.flags */
110
 
111
    /* Timing: All values in pixclocks, except pixclock (of course) */
112
    __u32 pixclock;         /* pixel clock in ps (pico seconds) */
113
    __u32 left_margin;      /* time from sync to picture    */
114
    __u32 right_margin;     /* time from picture to sync    */
115
    __u32 upper_margin;     /* time from sync to picture    */
116
    __u32 lower_margin;
117
    __u32 hsync_len;        /* length of horizontal sync    */
118
    __u32 vsync_len;        /* length of vertical sync  */
119
    __u32 sync;         /* see FB_SYNC_*        */
120
    __u32 vmode;            /* see FB_VMODE_*       */
121
    __u32 rotate;           /* angle we rotate counter clockwise */
122
    __u32 reserved[5];      /* Reserved for future compatibility */
123
};
124
 
125
 
126
 
127
struct fb_chroma {
128
    __u32 redx; /* in fraction of 1024 */
129
    __u32 greenx;
130
    __u32 bluex;
131
    __u32 whitex;
132
    __u32 redy;
133
    __u32 greeny;
134
    __u32 bluey;
135
    __u32 whitey;
136
};
137
 
138
struct fb_videomode {
139
    const char *name;   /* optional */
140
    u32 refresh;        /* optional */
141
    u32 xres;
142
    u32 yres;
143
    u32 pixclock;
144
    u32 left_margin;
145
    u32 right_margin;
146
    u32 upper_margin;
147
    u32 lower_margin;
148
    u32 hsync_len;
149
    u32 vsync_len;
150
    u32 sync;
151
    u32 vmode;
152
    u32 flag;
153
};
154
 
155
 
156
struct fb_monspecs {
157
    struct fb_chroma chroma;
158
    struct fb_videomode *modedb;    /* mode database */
159
    __u8  manufacturer[4];      /* Manufacturer */
160
    __u8  monitor[14];      /* Monitor String */
161
    __u8  serial_no[14];        /* Serial Number */
162
    __u8  ascii[14];        /* ? */
163
    __u32 modedb_len;       /* mode database length */
164
    __u32 model;            /* Monitor Model */
165
    __u32 serial;           /* Serial Number - Integer */
166
    __u32 year;         /* Year manufactured */
167
    __u32 week;         /* Week Manufactured */
168
    __u32 hfmin;            /* hfreq lower limit (Hz) */
169
    __u32 hfmax;            /* hfreq upper limit (Hz) */
170
    __u32 dclkmin;          /* pixelclock lower limit (Hz) */
171
    __u32 dclkmax;          /* pixelclock upper limit (Hz) */
172
    __u16 input;            /* display type - see FB_DISP_* */
173
    __u16 dpms;         /* DPMS support - see FB_DPMS_ */
174
    __u16 signal;           /* Signal Type - see FB_SIGNAL_* */
175
    __u16 vfmin;            /* vfreq lower limit (Hz) */
176
    __u16 vfmax;            /* vfreq upper limit (Hz) */
177
    __u16 gamma;            /* Gamma - in fractions of 100 */
178
    __u16 gtf   : 1;        /* supports GTF */
179
    __u16 misc;         /* Misc flags - see FB_MISC_* */
180
    __u8  version;          /* EDID version... */
181
    __u8  revision;         /* ...and revision */
182
    __u8  max_x;            /* Maximum horizontal size (cm) */
183
    __u8  max_y;            /* Maximum vertical size (cm) */
184
};
185
 
186
 
187
struct fb_info {
188
    int node;
189
    int flags;
190
//    struct mutex lock;      /* Lock for open/release/ioctl funcs */
191
//    struct mutex mm_lock;       /* Lock for fb_mmap and smem_* fields */
192
    struct fb_var_screeninfo var;   /* Current var */
193
    struct fb_fix_screeninfo fix;   /* Current fix */
194
    struct fb_monspecs monspecs;    /* Current Monitor specs */
195
//    struct work_struct queue;   /* Framebuffer event queue */
196
//    struct fb_pixmap pixmap;    /* Image hardware mapper */
197
//    struct fb_pixmap sprite;    /* Cursor hardware mapper */
198
//    struct fb_cmap cmap;        /* Current cmap */
199
    struct list_head modelist;      /* mode list */
200
    struct fb_videomode *mode;  /* current mode */
201
 
202
#ifdef CONFIG_FB_BACKLIGHT
203
    /* assigned backlight device */
204
    /* set before framebuffer registration,
205
       remove after unregister */
206
    struct backlight_device *bl_dev;
207
 
208
    /* Backlight level curve */
209
    struct mutex bl_curve_mutex;
210
    u8 bl_curve[FB_BACKLIGHT_LEVELS];
211
#endif
212
#ifdef CONFIG_FB_DEFERRED_IO
213
    struct delayed_work deferred_work;
214
    struct fb_deferred_io *fbdefio;
215
#endif
216
 
217
    struct fb_ops *fbops;
218
//    struct device *device;      /* This is the parent */
219
//   struct device *dev;     /* This is this fb device */
220
    int class_flag;                    /* private sysfs flags */
221
#ifdef CONFIG_FB_TILEBLITTING
222
    struct fb_tile_ops *tileops;    /* Tile Blitting */
223
#endif
224
    char __iomem *screen_base;  /* Virtual address */
225
    unsigned long screen_size;  /* Amount of ioremapped VRAM or 0 */
226
    void *pseudo_palette;       /* Fake palette of 16 colors */
227
#define FBINFO_STATE_RUNNING    0
228
#define FBINFO_STATE_SUSPENDED  1
229
    u32 state;          /* Hardware state i.e suspend */
230
    void *fbcon_par;                /* fbcon use-only private area */
231
    /* From here on everything is device dependent */
232
    void *par;
233
    /* we need the PCI or similiar aperture base/size not
234
       smem_start/size as smem_start may just be an object
235
       allocated inside the aperture so may not actually overlap */
236
    resource_size_t aperture_base;
237
    resource_size_t aperture_size;
238
};
239
 
240
 
241
 
242
struct radeon_fb_device {
243
	struct radeon_device		*rdev;
244
	struct drm_display_mode		*mode;
245
	struct radeon_framebuffer	*rfb;
246
    int                         crtc_count;
247
	/* crtc currently bound to this */
248
	uint32_t			crtc_ids[2];
249
};
250
 
251
int radeon_gem_fb_object_create(struct radeon_device *rdev, int size,
252
                 int alignment, int initial_domain,
253
                 bool discardable, bool kernel,
254
                 bool interruptible,
255
                 struct drm_gem_object **obj);
256
 
257
struct fb_info *framebuffer_alloc(size_t size);
258
 
259
#if 0
260
static int radeonfb_setcolreg(unsigned regno,
261
			      unsigned red,
262
			      unsigned green,
263
			      unsigned blue,
264
			      unsigned transp,
265
			      struct fb_info *info)
266
{
267
	struct radeon_fb_device *rfbdev = info->par;
268
	struct drm_device *dev = rfbdev->rdev->ddev;
269
	struct drm_crtc *crtc;
270
	int i;
271
 
272
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
273
		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
274
		struct drm_mode_set *modeset = &radeon_crtc->mode_set;
275
		struct drm_framebuffer *fb = modeset->fb;
276
 
277
		for (i = 0; i < rfbdev->crtc_count; i++) {
278
			if (crtc->base.id == rfbdev->crtc_ids[i]) {
279
				break;
280
			}
281
		}
282
		if (i == rfbdev->crtc_count) {
283
			continue;
284
		}
285
		if (regno > 255) {
286
			return 1;
287
		}
288
		if (fb->depth == 8) {
289
			radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno);
290
			return 0;
291
		}
292
 
293
		if (regno < 16) {
294
			switch (fb->depth) {
295
			case 15:
296
				fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
297
					((green & 0xf800) >>  6) |
298
					((blue & 0xf800) >> 11);
299
				break;
300
			case 16:
301
				fb->pseudo_palette[regno] = (red & 0xf800) |
302
					((green & 0xfc00) >>  5) |
303
					((blue  & 0xf800) >> 11);
304
				break;
305
			case 24:
306
			case 32:
307
				fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
308
					(green & 0xff00) |
309
					((blue  & 0xff00) >> 8);
310
				break;
311
			}
312
		}
313
	}
314
	return 0;
315
}
316
 
317
static int radeonfb_check_var(struct fb_var_screeninfo *var,
318
			      struct fb_info *info)
319
{
320
	struct radeon_fb_device *rfbdev = info->par;
321
	struct radeon_framebuffer *rfb = rfbdev->rfb;
322
	struct drm_framebuffer *fb = &rfb->base;
323
	int depth;
324
 
325
	if (var->pixclock == -1 || !var->pixclock) {
326
		return -EINVAL;
327
	}
328
	/* Need to resize the fb object !!! */
329
	if (var->xres > fb->width || var->yres > fb->height) {
330
		DRM_ERROR("Requested width/height is greater than current fb "
331
			   "object %dx%d > %dx%d\n", var->xres, var->yres,
332
			   fb->width, fb->height);
333
		DRM_ERROR("Need resizing code.\n");
334
		return -EINVAL;
335
	}
336
 
337
	switch (var->bits_per_pixel) {
338
	case 16:
339
		depth = (var->green.length == 6) ? 16 : 15;
340
		break;
341
	case 32:
342
		depth = (var->transp.length > 0) ? 32 : 24;
343
		break;
344
	default:
345
		depth = var->bits_per_pixel;
346
		break;
347
	}
348
 
349
	switch (depth) {
350
	case 8:
351
		var->red.offset = 0;
352
		var->green.offset = 0;
353
		var->blue.offset = 0;
354
		var->red.length = 8;
355
		var->green.length = 8;
356
		var->blue.length = 8;
357
		var->transp.length = 0;
358
		var->transp.offset = 0;
359
		break;
360
	case 15:
361
		var->red.offset = 10;
362
		var->green.offset = 5;
363
		var->blue.offset = 0;
364
		var->red.length = 5;
365
		var->green.length = 5;
366
		var->blue.length = 5;
367
		var->transp.length = 1;
368
		var->transp.offset = 15;
369
		break;
370
	case 16:
371
		var->red.offset = 11;
372
		var->green.offset = 5;
373
		var->blue.offset = 0;
374
		var->red.length = 5;
375
		var->green.length = 6;
376
		var->blue.length = 5;
377
		var->transp.length = 0;
378
		var->transp.offset = 0;
379
		break;
380
	case 24:
381
		var->red.offset = 16;
382
		var->green.offset = 8;
383
		var->blue.offset = 0;
384
		var->red.length = 8;
385
		var->green.length = 8;
386
		var->blue.length = 8;
387
		var->transp.length = 0;
388
		var->transp.offset = 0;
389
		break;
390
	case 32:
391
		var->red.offset = 16;
392
		var->green.offset = 8;
393
		var->blue.offset = 0;
394
		var->red.length = 8;
395
		var->green.length = 8;
396
		var->blue.length = 8;
397
		var->transp.length = 8;
398
		var->transp.offset = 24;
399
		break;
400
	default:
401
		return -EINVAL;
402
	}
403
	return 0;
404
}
405
 
406
#endif
407
 
408
 
409
/* this will let fbcon do the mode init */
410
static int radeonfb_set_par(struct fb_info *info)
411
{
412
	struct radeon_fb_device *rfbdev = info->par;
413
	struct drm_device *dev = rfbdev->rdev->ddev;
414
	struct fb_var_screeninfo *var = &info->var;
415
	struct drm_crtc *crtc;
416
	int ret;
417
	int i;
418
 
419
	if (var->pixclock != -1) {
420
		DRM_ERROR("PIXEL CLCOK SET\n");
421
		return -EINVAL;
422
	}
423
 
424
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
425
		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
426
 
427
		for (i = 0; i < rfbdev->crtc_count; i++) {
428
			if (crtc->base.id == rfbdev->crtc_ids[i]) {
429
				break;
430
			}
431
		}
432
		if (i == rfbdev->crtc_count) {
433
			continue;
434
		}
435
		if (crtc->fb == radeon_crtc->mode_set.fb) {
436
//           mutex_lock(&dev->mode_config.mutex);
437
			ret = crtc->funcs->set_config(&radeon_crtc->mode_set);
438
//           mutex_unlock(&dev->mode_config.mutex);
439
			if (ret) {
440
				return ret;
441
			}
442
		}
443
	}
444
	return 0;
445
}
446
 
447
#if 0
448
 
449
static int radeonfb_pan_display(struct fb_var_screeninfo *var,
450
				struct fb_info *info)
451
{
452
	struct radeon_fb_device *rfbdev = info->par;
453
	struct drm_device *dev = rfbdev->rdev->ddev;
454
	struct drm_mode_set *modeset;
455
	struct drm_crtc *crtc;
456
	struct radeon_crtc *radeon_crtc;
457
	int ret = 0;
458
	int i;
459
 
460
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
461
		for (i = 0; i < rfbdev->crtc_count; i++) {
462
			if (crtc->base.id == rfbdev->crtc_ids[i]) {
463
				break;
464
			}
465
		}
466
 
467
		if (i == rfbdev->crtc_count) {
468
			continue;
469
		}
470
 
471
		radeon_crtc = to_radeon_crtc(crtc);
472
		modeset = &radeon_crtc->mode_set;
473
 
474
		modeset->x = var->xoffset;
475
		modeset->y = var->yoffset;
476
 
477
		if (modeset->num_connectors) {
478
			mutex_lock(&dev->mode_config.mutex);
479
			ret = crtc->funcs->set_config(modeset);
480
			mutex_unlock(&dev->mode_config.mutex);
481
			if (!ret) {
482
				info->var.xoffset = var->xoffset;
483
				info->var.yoffset = var->yoffset;
484
			}
485
		}
486
	}
487
	return ret;
488
}
489
 
490
static void radeonfb_on(struct fb_info *info)
491
{
492
	struct radeon_fb_device *rfbdev = info->par;
493
	struct drm_device *dev = rfbdev->rdev->ddev;
494
	struct drm_crtc *crtc;
495
	struct drm_encoder *encoder;
496
	int i;
497
 
498
	/*
499
	 * For each CRTC in this fb, find all associated encoders
500
	 * and turn them off, then turn off the CRTC.
501
	 */
502
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
503
		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
504
 
505
		for (i = 0; i < rfbdev->crtc_count; i++) {
506
			if (crtc->base.id == rfbdev->crtc_ids[i]) {
507
				break;
508
			}
509
		}
510
 
511
		mutex_lock(&dev->mode_config.mutex);
512
		crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
513
		mutex_unlock(&dev->mode_config.mutex);
514
 
515
		/* Found a CRTC on this fb, now find encoders */
516
		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
517
			if (encoder->crtc == crtc) {
518
				struct drm_encoder_helper_funcs *encoder_funcs;
519
 
520
				encoder_funcs = encoder->helper_private;
521
				mutex_lock(&dev->mode_config.mutex);
522
				encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
523
				mutex_unlock(&dev->mode_config.mutex);
524
			}
525
		}
526
	}
527
}
528
 
529
static void radeonfb_off(struct fb_info *info, int dpms_mode)
530
{
531
	struct radeon_fb_device *rfbdev = info->par;
532
	struct drm_device *dev = rfbdev->rdev->ddev;
533
	struct drm_crtc *crtc;
534
	struct drm_encoder *encoder;
535
	int i;
536
 
537
	/*
538
	 * For each CRTC in this fb, find all associated encoders
539
	 * and turn them off, then turn off the CRTC.
540
	 */
541
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
542
		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
543
 
544
		for (i = 0; i < rfbdev->crtc_count; i++) {
545
			if (crtc->base.id == rfbdev->crtc_ids[i]) {
546
				break;
547
			}
548
		}
549
 
550
		/* Found a CRTC on this fb, now find encoders */
551
		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
552
			if (encoder->crtc == crtc) {
553
				struct drm_encoder_helper_funcs *encoder_funcs;
554
 
555
				encoder_funcs = encoder->helper_private;
556
				mutex_lock(&dev->mode_config.mutex);
557
				encoder_funcs->dpms(encoder, dpms_mode);
558
				mutex_unlock(&dev->mode_config.mutex);
559
			}
560
		}
561
		if (dpms_mode == DRM_MODE_DPMS_OFF) {
562
			mutex_lock(&dev->mode_config.mutex);
563
			crtc_funcs->dpms(crtc, dpms_mode);
564
			mutex_unlock(&dev->mode_config.mutex);
565
		}
566
	}
567
}
568
 
569
int radeonfb_blank(int blank, struct fb_info *info)
570
{
571
	switch (blank) {
572
	case FB_BLANK_UNBLANK:
573
		radeonfb_on(info);
574
		break;
575
	case FB_BLANK_NORMAL:
576
		radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
577
		break;
578
	case FB_BLANK_HSYNC_SUSPEND:
579
		radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
580
		break;
581
	case FB_BLANK_VSYNC_SUSPEND:
582
		radeonfb_off(info, DRM_MODE_DPMS_SUSPEND);
583
		break;
584
	case FB_BLANK_POWERDOWN:
585
		radeonfb_off(info, DRM_MODE_DPMS_OFF);
586
		break;
587
	}
588
	return 0;
589
}
590
 
591
static struct fb_ops radeonfb_ops = {
592
	.owner = THIS_MODULE,
593
	.fb_check_var = radeonfb_check_var,
594
	.fb_set_par = radeonfb_set_par,
595
	.fb_setcolreg = radeonfb_setcolreg,
596
	.fb_fillrect = cfb_fillrect,
597
	.fb_copyarea = cfb_copyarea,
598
	.fb_imageblit = cfb_imageblit,
599
	.fb_pan_display = radeonfb_pan_display,
600
	.fb_blank = radeonfb_blank,
601
};
602
 
603
/**
604
 * Curretly it is assumed that the old framebuffer is reused.
605
 *
606
 * LOCKING
607
 * caller should hold the mode config lock.
608
 *
609
 */
610
int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
611
{
612
	struct fb_info *info;
613
	struct drm_framebuffer *fb;
614
	struct drm_display_mode *mode = crtc->desired_mode;
615
 
616
	fb = crtc->fb;
617
	if (fb == NULL) {
618
		return 1;
619
	}
620
	info = fb->fbdev;
621
	if (info == NULL) {
622
		return 1;
623
	}
624
	if (mode == NULL) {
625
		return 1;
626
	}
627
	info->var.xres = mode->hdisplay;
628
	info->var.right_margin = mode->hsync_start - mode->hdisplay;
629
	info->var.hsync_len = mode->hsync_end - mode->hsync_start;
630
	info->var.left_margin = mode->htotal - mode->hsync_end;
631
	info->var.yres = mode->vdisplay;
632
	info->var.lower_margin = mode->vsync_start - mode->vdisplay;
633
	info->var.vsync_len = mode->vsync_end - mode->vsync_start;
634
	info->var.upper_margin = mode->vtotal - mode->vsync_end;
635
	info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100;
636
	/* avoid overflow */
637
	info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh;
638
 
639
	return 0;
640
}
641
EXPORT_SYMBOL(radeonfb_resize);
642
 
643
static struct drm_mode_set panic_mode;
644
 
645
int radeonfb_panic(struct notifier_block *n, unsigned long ununsed,
646
		  void *panic_str)
647
{
648
	DRM_ERROR("panic occurred, switching back to text console\n");
649
	drm_crtc_helper_set_config(&panic_mode);
650
	return 0;
651
}
652
EXPORT_SYMBOL(radeonfb_panic);
653
 
654
static struct notifier_block paniced = {
655
	.notifier_call = radeonfb_panic,
656
};
657
#endif
658
 
659
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp)
660
{
661
	int aligned = width;
662
	int align_large = (ASIC_IS_AVIVO(rdev));
663
	int pitch_mask = 0;
664
 
665
	switch (bpp / 8) {
666
	case 1:
667
		pitch_mask = align_large ? 255 : 127;
668
		break;
669
	case 2:
670
		pitch_mask = align_large ? 127 : 31;
671
		break;
672
	case 3:
673
	case 4:
674
		pitch_mask = align_large ? 63 : 15;
675
		break;
676
	}
677
 
678
	aligned += pitch_mask;
679
	aligned &= ~pitch_mask;
680
	return aligned;
681
}
682
 
683
int radeonfb_create(struct radeon_device *rdev,
684
		    uint32_t fb_width, uint32_t fb_height,
685
		    uint32_t surface_width, uint32_t surface_height,
686
		    struct radeon_framebuffer **rfb_p)
687
{
688
	struct fb_info *info;
689
	struct radeon_fb_device *rfbdev;
690
	struct drm_framebuffer *fb = NULL;
691
	struct radeon_framebuffer *rfb;
692
	struct drm_mode_fb_cmd mode_cmd;
693
	struct drm_gem_object *gobj = NULL;
694
	struct radeon_object *robj = NULL;
695
//   struct device *device = &rdev->pdev->dev;
696
	int size, aligned_size, ret;
697
	u64 fb_gpuaddr;
698
	void *fbptr = NULL;
699
	unsigned long tmp;
700
 
701
    ENTRY();
702
 
703
	mode_cmd.width = surface_width;
704
	mode_cmd.height = surface_height;
705
	mode_cmd.bpp = 32;
706
	/* need to align pitch with crtc limits */
707
	mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8);
708
    mode_cmd.depth = 32;
709
 
710
	size = mode_cmd.pitch * mode_cmd.height;
711
	aligned_size = ALIGN(size, PAGE_SIZE);
712
 
713
    ret = radeon_gem_fb_object_create(rdev, aligned_size, 0,
714
			RADEON_GEM_DOMAIN_VRAM,
715
            false, 0,
716
			false, &gobj);
717
 
718
 
719
	if (ret) {
720
		printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
721
		       surface_width, surface_height);
722
		ret = -ENOMEM;
723
		goto out;
724
	}
725
	robj = gobj->driver_private;
726
 
727
//   mutex_lock(&rdev->ddev->struct_mutex);
728
	fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
729
	if (fb == NULL) {
730
		DRM_ERROR("failed to allocate fb.\n");
731
		ret = -ENOMEM;
732
		goto out_unref;
733
	}
734
	ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
735
	if (ret) {
736
		printk(KERN_ERR "failed to pin framebuffer\n");
737
		ret = -ENOMEM;
738
		goto out_unref;
739
	}
740
 
741
	list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
742
 
743
	rfb = to_radeon_framebuffer(fb);
744
	*rfb_p = rfb;
745
	rdev->fbdev_rfb = rfb;
746
	rdev->fbdev_robj = robj;
747
 
748
    info = framebuffer_alloc(sizeof(struct radeon_fb_device));
749
	if (info == NULL) {
750
		ret = -ENOMEM;
751
		goto out_unref;
752
	}
753
	rfbdev = info->par;
754
 
755
//   ret = radeon_object_kmap(robj, &fbptr);
756
//   if (ret) {
757
//       goto out_unref;
758
//   }
759
 
760
    fbptr = (void*)0xFE000000; // LFB_BASE
761
 
762
 
763
	strcpy(info->fix.id, "radeondrmfb");
764
	info->fix.type = FB_TYPE_PACKED_PIXELS;
765
	info->fix.visual = FB_VISUAL_TRUECOLOR;
766
	info->fix.type_aux = 0;
767
	info->fix.xpanstep = 1; /* doing it in hw */
768
	info->fix.ypanstep = 1; /* doing it in hw */
769
	info->fix.ywrapstep = 0;
770
//   info->fix.accel = FB_ACCEL_NONE;
771
	info->fix.type_aux = 0;
772
//   info->flags = FBINFO_DEFAULT;
773
//   info->fbops = &radeonfb_ops;
774
	info->fix.line_length = fb->pitch;
775
	tmp = fb_gpuaddr - rdev->mc.vram_location;
776
	info->fix.smem_start = rdev->mc.aper_base + tmp;
777
	info->fix.smem_len = size;
778
	info->screen_base = fbptr;
779
	info->screen_size = size;
780
	info->pseudo_palette = fb->pseudo_palette;
781
	info->var.xres_virtual = fb->width;
782
	info->var.yres_virtual = fb->height;
783
	info->var.bits_per_pixel = fb->bits_per_pixel;
784
	info->var.xoffset = 0;
785
	info->var.yoffset = 0;
786
//   info->var.activate = FB_ACTIVATE_NOW;
787
	info->var.height = -1;
788
	info->var.width = -1;
789
	info->var.xres = fb_width;
790
	info->var.yres = fb_height;
791
	info->fix.mmio_start = 0;
792
	info->fix.mmio_len = 0;
793
//   info->pixmap.size = 64*1024;
794
//   info->pixmap.buf_align = 8;
795
//   info->pixmap.access_align = 32;
796
//   info->pixmap.flags = FB_PIXMAP_SYSTEM;
797
//   info->pixmap.scan_align = 1;
798
	if (info->screen_base == NULL) {
799
		ret = -ENOSPC;
800
		goto out_unref;
801
	}
802
	DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
803
	DRM_INFO("vram apper at 0x%lX\n",  (unsigned long)rdev->mc.aper_base);
804
	DRM_INFO("size %lu\n", (unsigned long)size);
805
	DRM_INFO("fb depth is %d\n", fb->depth);
806
	DRM_INFO("   pitch is %d\n", fb->pitch);
807
 
808
	switch (fb->depth) {
809
	case 8:
810
		info->var.red.offset = 0;
811
		info->var.green.offset = 0;
812
		info->var.blue.offset = 0;
813
		info->var.red.length = 8; /* 8bit DAC */
814
		info->var.green.length = 8;
815
		info->var.blue.length = 8;
816
		info->var.transp.offset = 0;
817
		info->var.transp.length = 0;
818
		break;
819
	case 15:
820
		info->var.red.offset = 10;
821
		info->var.green.offset = 5;
822
		info->var.blue.offset = 0;
823
		info->var.red.length = 5;
824
		info->var.green.length = 5;
825
		info->var.blue.length = 5;
826
		info->var.transp.offset = 15;
827
		info->var.transp.length = 1;
828
		break;
829
	case 16:
830
		info->var.red.offset = 11;
831
		info->var.green.offset = 5;
832
		info->var.blue.offset = 0;
833
		info->var.red.length = 5;
834
		info->var.green.length = 6;
835
		info->var.blue.length = 5;
836
		info->var.transp.offset = 0;
837
		break;
838
	case 24:
839
		info->var.red.offset = 16;
840
		info->var.green.offset = 8;
841
		info->var.blue.offset = 0;
842
		info->var.red.length = 8;
843
		info->var.green.length = 8;
844
		info->var.blue.length = 8;
845
		info->var.transp.offset = 0;
846
		info->var.transp.length = 0;
847
		break;
848
	case 32:
849
		info->var.red.offset = 16;
850
		info->var.green.offset = 8;
851
		info->var.blue.offset = 0;
852
		info->var.red.length = 8;
853
		info->var.green.length = 8;
854
		info->var.blue.length = 8;
855
		info->var.transp.offset = 24;
856
		info->var.transp.length = 8;
857
		break;
858
	default:
859
		break;
860
	}
861
 
862
    dbgprintf("fb = %x\n", fb);
863
 
864
	fb->fbdev = info;
865
	rfbdev->rfb = rfb;
866
	rfbdev->rdev = rdev;
867
 
868
//   mutex_unlock(&rdev->ddev->struct_mutex);
869
	return 0;
870
 
871
out_unref:
872
	if (robj) {
873
//       radeon_object_kunmap(robj);
874
	}
875
	if (fb && ret) {
876
		list_del(&fb->filp_head);
877
 //      drm_gem_object_unreference(gobj);
878
//       drm_framebuffer_cleanup(fb);
879
		kfree(fb);
880
	}
881
//   drm_gem_object_unreference(gobj);
882
//   mutex_unlock(&rdev->ddev->struct_mutex);
883
out:
884
	return ret;
885
}
886
 
887
static int radeonfb_single_fb_probe(struct radeon_device *rdev)
888
{
889
	struct drm_crtc *crtc;
890
	struct drm_connector *connector;
891
	unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
892
	unsigned int surface_width = 0, surface_height = 0;
893
	int new_fb = 0;
894
	int crtc_count = 0;
895
	int ret, i, conn_count = 0;
896
	struct radeon_framebuffer *rfb;
897
	struct fb_info *info;
898
	struct radeon_fb_device *rfbdev;
899
	struct drm_mode_set *modeset = NULL;
900
 
901
    ENTRY();
902
 
903
	/* first up get a count of crtcs now in use and new min/maxes width/heights */
904
	list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
905
		if (drm_helper_crtc_in_use(crtc)) {
906
			if (crtc->desired_mode) {
907
				if (crtc->desired_mode->hdisplay < fb_width)
908
					fb_width = crtc->desired_mode->hdisplay;
909
 
910
				if (crtc->desired_mode->vdisplay < fb_height)
911
					fb_height = crtc->desired_mode->vdisplay;
912
 
913
				if (crtc->desired_mode->hdisplay > surface_width)
914
					surface_width = crtc->desired_mode->hdisplay;
915
 
916
				if (crtc->desired_mode->vdisplay > surface_height)
917
					surface_height = crtc->desired_mode->vdisplay;
918
			}
919
			crtc_count++;
920
		}
921
	}
922
 
923
	if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
924
		/* hmm everyone went away - assume VGA cable just fell out
925
		   and will come back later. */
926
 
927
        dbgprintf("crtc count %x width %x height %x\n",
928
                   crtc_count, fb_width, fb_height);
929
		return 0;
930
	}
931
 
932
	/* do we have an fb already? */
933
	if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) {
934
		/* create an fb if we don't have one */
935
		ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb);
936
		if (ret) {
937
			return -EINVAL;
938
		}
939
		new_fb = 1;
940
	} else {
941
		struct drm_framebuffer *fb;
942
		fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head);
943
		rfb = to_radeon_framebuffer(fb);
944
 
945
		/* if someone hotplugs something bigger than we have already allocated, we are pwned.
946
		   As really we can't resize an fbdev that is in the wild currently due to fbdev
947
		   not really being designed for the lower layers moving stuff around under it.
948
		   - so in the grand style of things - punt. */
949
		if ((fb->width < surface_width) || (fb->height < surface_height)) {
950
			DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
951
			return -EINVAL;
952
		}
953
	}
954
 
955
	info = rfb->base.fbdev;
956
	rdev->fbdev_info = info;
957
	rfbdev = info->par;
958
 
959
	crtc_count = 0;
960
	/* okay we need to setup new connector sets in the crtcs */
961
	list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
962
		struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
963
		modeset = &radeon_crtc->mode_set;
964
		modeset->fb = &rfb->base;
965
		conn_count = 0;
966
		list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) {
967
			if (connector->encoder)
968
				if (connector->encoder->crtc == modeset->crtc) {
969
					modeset->connectors[conn_count] = connector;
970
					conn_count++;
971
					if (conn_count > RADEONFB_CONN_LIMIT)
972
						BUG();
973
				}
974
		}
975
 
976
		for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++)
977
			modeset->connectors[i] = NULL;
978
 
979
 
980
		rfbdev->crtc_ids[crtc_count++] = crtc->base.id;
981
 
982
		modeset->num_connectors = conn_count;
983
		if (modeset->crtc->desired_mode) {
984
			if (modeset->mode) {
985
				drm_mode_destroy(rdev->ddev, modeset->mode);
986
			}
987
			modeset->mode = drm_mode_duplicate(rdev->ddev,
988
							   modeset->crtc->desired_mode);
989
		}
990
	}
991
	rfbdev->crtc_count = crtc_count;
992
 
993
	if (new_fb) {
994
		info->var.pixclock = -1;
995
//       if (register_framebuffer(info) < 0)
996
//           return -EINVAL;
997
	} else {
998
		radeonfb_set_par(info);
999
	}
1000
	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
1001
	       info->fix.id);
1002
 
1003
	/* Switch back to kernel console on panic */
1004
//   panic_mode = *modeset;
1005
//   atomic_notifier_chain_register(&panic_notifier_list, &paniced);
1006
//   printk(KERN_INFO "registered panic notifier\n");
1007
    LEAVE();
1008
 
1009
	return 0;
1010
}
1011
 
1012
int radeonfb_probe(struct drm_device *dev)
1013
{
1014
	int ret;
1015
 
1016
	/* something has changed in the lower levels of hell - deal with it
1017
	   here */
1018
 
1019
	/* two modes : a) 1 fb to rule all crtcs.
1020
	               b) one fb per crtc.
1021
	   two actions 1) new connected device
1022
	               2) device removed.
1023
	   case a/1 : if the fb surface isn't big enough - resize the surface fb.
1024
	              if the fb size isn't big enough - resize fb into surface.
1025
		      if everything big enough configure the new crtc/etc.
1026
	   case a/2 : undo the configuration
1027
	              possibly resize down the fb to fit the new configuration.
1028
           case b/1 : see if it is on a new crtc - setup a new fb and add it.
1029
	   case b/2 : teardown the new fb.
1030
	*/
1031
	ret = radeonfb_single_fb_probe(dev->dev_private);
1032
	return ret;
1033
}
1034
EXPORT_SYMBOL(radeonfb_probe);
1035
 
1036
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
1037
{
1038
	struct fb_info *info;
1039
	struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
1040
	struct radeon_object *robj;
1041
 
1042
	if (!fb) {
1043
		return -EINVAL;
1044
	}
1045
	info = fb->fbdev;
1046
	if (info) {
1047
		robj = rfb->obj->driver_private;
1048
//       unregister_framebuffer(info);
1049
//       radeon_object_kunmap(robj);
1050
//       radeon_object_unpin(robj);
1051
//       framebuffer_release(info);
1052
	}
1053
 
1054
	printk(KERN_INFO "unregistered panic notifier\n");
1055
//   atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
1056
//   memset(&panic_mode, 0, sizeof(struct drm_mode_set));
1057
	return 0;
1058
}
1059
EXPORT_SYMBOL(radeonfb_remove);
1060
 
1061
 
1062
/**
1063
 * Allocate a GEM object of the specified size with shmfs backing store
1064
 */
1065
struct drm_gem_object *
1066
drm_gem_object_alloc(struct drm_device *dev, size_t size)
1067
{
1068
    struct drm_gem_object *obj;
1069
 
1070
    BUG_ON((size & (PAGE_SIZE - 1)) != 0);
1071
 
1072
    obj = kzalloc(sizeof(*obj), GFP_KERNEL);
1073
 
1074
    obj->dev = dev;
1075
//    obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
1076
//    if (IS_ERR(obj->filp)) {
1077
//        kfree(obj);
1078
//        return NULL;
1079
//    }
1080
 
1081
//    kref_init(&obj->refcount);
1082
//    kref_init(&obj->handlecount);
1083
    obj->size = size;
1084
 
1085
//    if (dev->driver->gem_init_object != NULL &&
1086
//        dev->driver->gem_init_object(obj) != 0) {
1087
//        fput(obj->filp);
1088
//        kfree(obj);
1089
//        return NULL;
1090
//    }
1091
//    atomic_inc(&dev->object_count);
1092
//    atomic_add(obj->size, &dev->object_memory);
1093
    return obj;
1094
}
1095
 
1096
 
1097
int radeon_gem_fb_object_create(struct radeon_device *rdev, int size,
1098
                 int alignment, int initial_domain,
1099
                 bool discardable, bool kernel,
1100
                 bool interruptible,
1101
                 struct drm_gem_object **obj)
1102
{
1103
    struct drm_gem_object *gobj;
1104
    struct radeon_object *robj;
1105
 
1106
    *obj = NULL;
1107
    gobj = drm_gem_object_alloc(rdev->ddev, size);
1108
    if (!gobj) {
1109
        return -ENOMEM;
1110
    }
1111
    /* At least align on page size */
1112
    if (alignment < PAGE_SIZE) {
1113
        alignment = PAGE_SIZE;
1114
    }
1115
 
1116
    robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL);
1117
    if (!robj) {
1118
        DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
1119
              size, initial_domain, alignment);
1120
//       mutex_lock(&rdev->ddev->struct_mutex);
1121
//       drm_gem_object_unreference(gobj);
1122
//       mutex_unlock(&rdev->ddev->struct_mutex);
1123
        return -ENOMEM;;
1124
    }
1125
    robj->rdev = rdev;
1126
    robj->gobj = gobj;
1127
    INIT_LIST_HEAD(&robj->list);
1128
 
1129
    robj->flags = TTM_PL_FLAG_VRAM;
1130
 
1131
    struct drm_mm_node *vm_node;
1132
 
1133
    vm_node = kzalloc(sizeof(*vm_node),0);
1134
 
1135
    vm_node->free = 0;
1136
    vm_node->size = 0x800000 >> 12;
1137
    vm_node->start = 0;
1138
    vm_node->mm = NULL;
1139
 
1140
    robj->mm_node = vm_node;
1141
 
1142
    robj->vm_addr = ((uint32_t)robj->mm_node->start);
1143
 
1144
    gobj->driver_private = robj;
1145
    *obj = gobj;
1146
    return 0;
1147
}
1148
 
1149
 
1150
struct fb_info *framebuffer_alloc(size_t size)
1151
{
1152
#define BYTES_PER_LONG (BITS_PER_LONG/8)
1153
#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
1154
        int fb_info_size = sizeof(struct fb_info);
1155
        struct fb_info *info;
1156
        char *p;
1157
 
1158
        if (size)
1159
                fb_info_size += PADDING;
1160
 
1161
        p = kzalloc(fb_info_size + size, GFP_KERNEL);
1162
 
1163
        if (!p)
1164
                return NULL;
1165
 
1166
        info = (struct fb_info *) p;
1167
 
1168
        if (size)
1169
                info->par = p + fb_info_size;
1170
 
1171
        return info;
1172
#undef PADDING
1173
#undef BYTES_PER_LONG
1174
}
1175