~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/staging/gma500/psb_fb.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
 * Copyright (c) 2007, Intel Corporation.
 
3
 * All Rights Reserved.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify it
 
6
 * under the terms and conditions of the GNU General Public License,
 
7
 * version 2, as published by the Free Software Foundation.
 
8
 *
 
9
 * This program is distributed in the hope it will be useful, but WITHOUT
 
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
12
 * more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along with
 
15
 * this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 
17
 *
 
18
 **************************************************************************/
 
19
 
 
20
#include <linux/module.h>
 
21
#include <linux/kernel.h>
 
22
#include <linux/errno.h>
 
23
#include <linux/string.h>
 
24
#include <linux/mm.h>
 
25
#include <linux/tty.h>
 
26
#include <linux/slab.h>
 
27
#include <linux/delay.h>
 
28
#include <linux/fb.h>
 
29
#include <linux/init.h>
 
30
#include <linux/console.h>
 
31
 
 
32
#include <drm/drmP.h>
 
33
#include <drm/drm.h>
 
34
#include <drm/drm_crtc.h>
 
35
 
 
36
#include "psb_drv.h"
 
37
#include "psb_intel_reg.h"
 
38
#include "psb_intel_drv.h"
 
39
#include "psb_ttm_userobj_api.h"
 
40
#include "psb_fb.h"
 
41
#include "psb_sgx.h"
 
42
#include "psb_pvr_glue.h"
 
43
 
 
44
static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
 
45
static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 
46
                                              struct drm_file *file_priv,
 
47
                                              unsigned int *handle);
 
48
 
 
49
static const struct drm_framebuffer_funcs psb_fb_funcs = {
 
50
        .destroy = psb_user_framebuffer_destroy,
 
51
        .create_handle = psb_user_framebuffer_create_handle,
 
52
};
 
53
 
 
54
#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
 
55
 
 
56
void *psbfb_vdc_reg(struct drm_device *dev)
 
57
{
 
58
        struct drm_psb_private *dev_priv;
 
59
        dev_priv = (struct drm_psb_private *) dev->dev_private;
 
60
        return dev_priv->vdc_reg;
 
61
}
 
62
/*EXPORT_SYMBOL(psbfb_vdc_reg); */
 
63
 
 
64
static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
65
                           unsigned blue, unsigned transp,
 
66
                           struct fb_info *info)
 
67
{
 
68
        struct psb_fbdev *fbdev = info->par;
 
69
        struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
 
70
        uint32_t v;
 
71
 
 
72
        if (!fb)
 
73
                return -ENOMEM;
 
74
 
 
75
        if (regno > 255)
 
76
                return 1;
 
77
 
 
78
        red = CMAP_TOHW(red, info->var.red.length);
 
79
        blue = CMAP_TOHW(blue, info->var.blue.length);
 
80
        green = CMAP_TOHW(green, info->var.green.length);
 
81
        transp = CMAP_TOHW(transp, info->var.transp.length);
 
82
 
 
83
        v = (red << info->var.red.offset) |
 
84
            (green << info->var.green.offset) |
 
85
            (blue << info->var.blue.offset) |
 
86
            (transp << info->var.transp.offset);
 
87
 
 
88
        if (regno < 16) {
 
89
                switch (fb->bits_per_pixel) {
 
90
                case 16:
 
91
                        ((uint32_t *) info->pseudo_palette)[regno] = v;
 
92
                        break;
 
93
                case 24:
 
94
                case 32:
 
95
                        ((uint32_t *) info->pseudo_palette)[regno] = v;
 
96
                        break;
 
97
                }
 
98
        }
 
99
 
 
100
        return 0;
 
101
}
 
102
 
 
103
static int psbfb_kms_off(struct drm_device *dev, int suspend)
 
104
{
 
105
        struct drm_framebuffer *fb = 0;
 
106
        struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
107
        DRM_DEBUG("psbfb_kms_off_ioctl\n");
 
108
 
 
109
        mutex_lock(&dev->mode_config.mutex);
 
110
        list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 
111
                struct fb_info *info = psbfb->fbdev;
 
112
 
 
113
                if (suspend) {
 
114
                        fb_set_suspend(info, 1);
 
115
                        drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
 
116
                }
 
117
        }
 
118
        mutex_unlock(&dev->mode_config.mutex);
 
119
        return 0;
 
120
}
 
121
 
 
122
int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
 
123
                        struct drm_file *file_priv)
 
124
{
 
125
        int ret;
 
126
 
 
127
        if (drm_psb_no_fb)
 
128
                return 0;
 
129
        console_lock();
 
130
        ret = psbfb_kms_off(dev, 0);
 
131
        console_unlock();
 
132
 
 
133
        return ret;
 
134
}
 
135
 
 
136
static int psbfb_kms_on(struct drm_device *dev, int resume)
 
137
{
 
138
        struct drm_framebuffer *fb = 0;
 
139
        struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
140
 
 
141
        DRM_DEBUG("psbfb_kms_on_ioctl\n");
 
142
 
 
143
        mutex_lock(&dev->mode_config.mutex);
 
144
        list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 
145
                struct fb_info *info = psbfb->fbdev;
 
146
 
 
147
                if (resume) {
 
148
                        fb_set_suspend(info, 0);
 
149
                        drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
 
150
                }
 
151
        }
 
152
        mutex_unlock(&dev->mode_config.mutex);
 
153
 
 
154
        return 0;
 
155
}
 
156
 
 
157
int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
 
158
                       struct drm_file *file_priv)
 
159
{
 
160
        int ret;
 
161
 
 
162
        if (drm_psb_no_fb)
 
163
                return 0;
 
164
        console_lock();
 
165
        ret = psbfb_kms_on(dev, 0);
 
166
        console_unlock();
 
167
        drm_helper_disable_unused_functions(dev);
 
168
        return ret;
 
169
}
 
170
 
 
171
void psbfb_suspend(struct drm_device *dev)
 
172
{
 
173
        console_lock();
 
174
        psbfb_kms_off(dev, 1);
 
175
        console_unlock();
 
176
}
 
177
 
 
178
void psbfb_resume(struct drm_device *dev)
 
179
{
 
180
        console_lock();
 
181
        psbfb_kms_on(dev, 1);
 
182
        console_unlock();
 
183
        drm_helper_disable_unused_functions(dev);
 
184
}
 
185
 
 
186
static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
187
{
 
188
        int page_num = 0;
 
189
        int i;
 
190
        unsigned long address = 0;
 
191
        int ret;
 
192
        unsigned long pfn;
 
193
        struct psb_framebuffer *psbfb = vma->vm_private_data;
 
194
        struct drm_device *dev = psbfb->base.dev;
 
195
        struct drm_psb_private *dev_priv = dev->dev_private;
 
196
        struct psb_gtt *pg = dev_priv->pg;
 
197
        unsigned long phys_addr = (unsigned long)pg->stolen_base;;
 
198
 
 
199
        page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 
200
 
 
201
        address = (unsigned long)vmf->virtual_address;
 
202
 
 
203
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
204
 
 
205
        for (i = 0; i < page_num; i++) {
 
206
                pfn = (phys_addr >> PAGE_SHIFT); /* phys_to_pfn(phys_addr); */
 
207
 
 
208
                ret = vm_insert_mixed(vma, address, pfn);
 
209
                if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
 
210
                        break;
 
211
                else if (unlikely(ret != 0)) {
 
212
                        ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
 
213
                        return ret;
 
214
                }
 
215
 
 
216
                address += PAGE_SIZE;
 
217
                phys_addr += PAGE_SIZE;
 
218
        }
 
219
 
 
220
        return VM_FAULT_NOPAGE;
 
221
}
 
222
 
 
223
static void psbfb_vm_open(struct vm_area_struct *vma)
 
224
{
 
225
        DRM_DEBUG("vm_open\n");
 
226
}
 
227
 
 
228
static void psbfb_vm_close(struct vm_area_struct *vma)
 
229
{
 
230
        DRM_DEBUG("vm_close\n");
 
231
}
 
232
 
 
233
static struct vm_operations_struct psbfb_vm_ops = {
 
234
        .fault  = psbfb_vm_fault,
 
235
        .open   = psbfb_vm_open,
 
236
        .close  = psbfb_vm_close
 
237
};
 
238
 
 
239
static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
240
{
 
241
        struct psb_fbdev *fbdev = info->par;
 
242
        struct psb_framebuffer *psbfb = fbdev->pfb;
 
243
        char *fb_screen_base = NULL;
 
244
        struct drm_device *dev = psbfb->base.dev;
 
245
        struct drm_psb_private *dev_priv = dev->dev_private;
 
246
        struct psb_gtt *pg = dev_priv->pg;
 
247
 
 
248
        if (vma->vm_pgoff != 0)
 
249
                return -EINVAL;
 
250
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
 
251
                return -EINVAL;
 
252
 
 
253
        if (!psbfb->addr_space)
 
254
                psbfb->addr_space = vma->vm_file->f_mapping;
 
255
 
 
256
        fb_screen_base = (char *)info->screen_base;
 
257
 
 
258
        DRM_DEBUG("vm_pgoff 0x%lx, screen base %p vram_addr %p\n",
 
259
                                vma->vm_pgoff, fb_screen_base, pg->vram_addr);
 
260
 
 
261
        /*if using stolen memory, */
 
262
        if (fb_screen_base == pg->vram_addr) {
 
263
                vma->vm_ops = &psbfb_vm_ops;
 
264
                vma->vm_private_data = (void *)psbfb;
 
265
                vma->vm_flags |= VM_RESERVED | VM_IO |
 
266
                                                VM_MIXEDMAP | VM_DONTEXPAND;
 
267
        } else {
 
268
        /*using IMG meminfo, can I use pvrmmap to map it?*/
 
269
 
 
270
        }
 
271
 
 
272
        return 0;
 
273
}
 
274
 
 
275
 
 
276
static struct fb_ops psbfb_ops = {
 
277
        .owner = THIS_MODULE,
 
278
        .fb_check_var = drm_fb_helper_check_var,
 
279
        .fb_set_par = drm_fb_helper_set_par,
 
280
        .fb_blank = drm_fb_helper_blank,
 
281
        .fb_setcolreg = psbfb_setcolreg,
 
282
        .fb_fillrect = psbfb_fillrect,
 
283
        .fb_copyarea = psbfb_copyarea,
 
284
        .fb_imageblit = psbfb_imageblit,
 
285
        .fb_mmap = psbfb_mmap,
 
286
        .fb_sync = psbfb_sync,
 
287
};
 
288
 
 
289
static struct drm_framebuffer *psb_framebuffer_create
 
290
                        (struct drm_device *dev, struct drm_mode_fb_cmd *r,
 
291
                         void *mm_private)
 
292
{
 
293
        struct psb_framebuffer *fb;
 
294
        int ret;
 
295
 
 
296
        fb = kzalloc(sizeof(*fb), GFP_KERNEL);
 
297
        if (!fb)
 
298
                return NULL;
 
299
 
 
300
        ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
 
301
 
 
302
        if (ret)
 
303
                goto err;
 
304
 
 
305
        drm_helper_mode_fill_fb_struct(&fb->base, r);
 
306
 
 
307
        fb->bo = mm_private;
 
308
 
 
309
        return &fb->base;
 
310
 
 
311
err:
 
312
        kfree(fb);
 
313
        return NULL;
 
314
}
 
315
 
 
316
static struct drm_framebuffer *psb_user_framebuffer_create
 
317
                        (struct drm_device *dev, struct drm_file *filp,
 
318
                         struct drm_mode_fb_cmd *r)
 
319
{
 
320
        struct ttm_buffer_object *bo = NULL;
 
321
        uint64_t size;
 
322
 
 
323
        bo = ttm_buffer_object_lookup(psb_fpriv(filp)->tfile, r->handle);
 
324
        if (!bo)
 
325
                return NULL;
 
326
 
 
327
        /* JB: TODO not drop, make smarter */
 
328
        size = ((uint64_t) bo->num_pages) << PAGE_SHIFT;
 
329
        if (size < r->width * r->height * 4)
 
330
                return NULL;
 
331
 
 
332
        /* JB: TODO not drop, refcount buffer */
 
333
        return psb_framebuffer_create(dev, r, bo);
 
334
 
 
335
#if 0
 
336
        struct psb_framebuffer *psbfb;
 
337
        struct drm_framebuffer *fb;
 
338
        struct fb_info *info;
 
339
        void *psKernelMemInfo = NULL;
 
340
        void * hKernelMemInfo = (void *)r->handle;
 
341
        struct drm_psb_private *dev_priv
 
342
                = (struct drm_psb_private *)dev->dev_private;
 
343
        struct psb_fbdev *fbdev = dev_priv->fbdev;
 
344
        struct psb_gtt *pg = dev_priv->pg;
 
345
        int ret;
 
346
        uint32_t offset;
 
347
        uint64_t size;
 
348
 
 
349
        ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
 
350
        if (ret) {
 
351
                DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
 
352
                                                (u32)hKernelMemInfo);
 
353
                return NULL;
 
354
        }
 
355
 
 
356
        DRM_DEBUG("Got Kernel MemInfo for handle %lx\n",
 
357
                  (u32)hKernelMemInfo);
 
358
 
 
359
        /* JB: TODO not drop, make smarter */
 
360
        size = psKernelMemInfo->ui32AllocSize;
 
361
        if (size < r->height * r->pitch)
 
362
                return NULL;
 
363
 
 
364
        /* JB: TODO not drop, refcount buffer */
 
365
        /* return psb_framebuffer_create(dev, r, bo); */
 
366
 
 
367
        fb = psb_framebuffer_create(dev, r, (void *)psKernelMemInfo);
 
368
        if (!fb) {
 
369
                DRM_ERROR("failed to allocate fb.\n");
 
370
                return NULL;
 
371
        }
 
372
 
 
373
        psbfb = to_psb_fb(fb);
 
374
        psbfb->size = size;
 
375
        psbfb->hKernelMemInfo = hKernelMemInfo;
 
376
 
 
377
        DRM_DEBUG("Mapping to gtt..., KernelMemInfo %p\n", psKernelMemInfo);
 
378
 
 
379
        /*if not VRAM, map it into tt aperture*/
 
380
        if (psKernelMemInfo->pvLinAddrKM != pg->vram_addr) {
 
381
                ret = psb_gtt_map_meminfo(dev, hKernelMemInfo, &offset);
 
382
                if (ret) {
 
383
                        DRM_ERROR("map meminfo for 0x%x failed\n",
 
384
                                  (u32)hKernelMemInfo);
 
385
                        return NULL;
 
386
                }
 
387
                psbfb->offset = (offset << PAGE_SHIFT);
 
388
        } else {
 
389
                psbfb->offset = 0;
 
390
        }
 
391
        info = framebuffer_alloc(0, &dev->pdev->dev);
 
392
        if (!info)
 
393
                return NULL;
 
394
 
 
395
        strcpy(info->fix.id, "psbfb");
 
396
 
 
397
        info->flags = FBINFO_DEFAULT;
 
398
        info->fix.accel = FB_ACCEL_I830;        /*FIXMEAC*/
 
399
        info->fbops = &psbfb_ops;
 
400
 
 
401
        info->fix.smem_start = dev->mode_config.fb_base;
 
402
        info->fix.smem_len = size;
 
403
 
 
404
        info->screen_base = psKernelMemInfo->pvLinAddrKM;
 
405
        info->screen_size = size;
 
406
 
 
407
        drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
 
408
        drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
 
409
                                                        fb->width, fb->height);
 
410
 
 
411
        info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
 
412
        info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
 
413
 
 
414
        info->pixmap.size = 64 * 1024;
 
415
        info->pixmap.buf_align = 8;
 
416
        info->pixmap.access_align = 32;
 
417
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
418
        info->pixmap.scan_align = 1;
 
419
 
 
420
        psbfb->fbdev = info;
 
421
        fbdev->pfb = psbfb;
 
422
 
 
423
        fbdev->psb_fb_helper.fb = fb;
 
424
        fbdev->psb_fb_helper.fbdev = info;
 
425
        MRSTLFBHandleChangeFB(dev, psbfb);
 
426
 
 
427
        return fb;
 
428
#endif
 
429
}
 
430
 
 
431
static int psbfb_create(struct psb_fbdev *fbdev,
 
432
                                struct drm_fb_helper_surface_size *sizes)
 
433
{
 
434
        struct drm_device *dev = fbdev->psb_fb_helper.dev;
 
435
        struct drm_psb_private *dev_priv = dev->dev_private;
 
436
        struct psb_gtt *pg = dev_priv->pg;
 
437
        struct fb_info *info;
 
438
        struct drm_framebuffer *fb;
 
439
        struct psb_framebuffer *psbfb;
 
440
        struct drm_mode_fb_cmd mode_cmd;
 
441
        struct device *device = &dev->pdev->dev;
 
442
 
 
443
        struct ttm_buffer_object *fbo = NULL;
 
444
        int size, aligned_size;
 
445
        int ret;
 
446
 
 
447
        mode_cmd.width = sizes->surface_width;
 
448
        mode_cmd.height = sizes->surface_height;
 
449
 
 
450
        mode_cmd.bpp = 32;
 
451
        /* HW requires pitch to be 64 byte aligned */
 
452
        mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
 
453
        mode_cmd.depth = 24;
 
454
 
 
455
        size = mode_cmd.pitch * mode_cmd.height;
 
456
        aligned_size = ALIGN(size, PAGE_SIZE);
 
457
 
 
458
        mutex_lock(&dev->struct_mutex);
 
459
        fb = psb_framebuffer_create(dev, &mode_cmd, fbo);
 
460
        if (!fb) {
 
461
                DRM_ERROR("failed to allocate fb.\n");
 
462
                ret = -ENOMEM;
 
463
                goto out_err1;
 
464
        }
 
465
        psbfb = to_psb_fb(fb);
 
466
        psbfb->size = size;
 
467
 
 
468
        info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
 
469
        if (!info) {
 
470
                ret = -ENOMEM;
 
471
                goto out_err0;
 
472
        }
 
473
 
 
474
        info->par = fbdev;
 
475
 
 
476
        psbfb->fbdev = info;
 
477
 
 
478
        fbdev->psb_fb_helper.fb = fb;
 
479
        fbdev->psb_fb_helper.fbdev = info;
 
480
        fbdev->pfb = psbfb;
 
481
 
 
482
        strcpy(info->fix.id, "psbfb");
 
483
 
 
484
        info->flags = FBINFO_DEFAULT;
 
485
        info->fbops = &psbfb_ops;
 
486
        info->fix.smem_start = dev->mode_config.fb_base;
 
487
        info->fix.smem_len = size;
 
488
        info->screen_base = (char *)pg->vram_addr;
 
489
        info->screen_size = size;
 
490
        memset(info->screen_base, 0, size);
 
491
 
 
492
        drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
 
493
        drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
 
494
                                sizes->fb_width, sizes->fb_height);
 
495
 
 
496
        info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
 
497
        info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
 
498
 
 
499
        info->pixmap.size = 64 * 1024;
 
500
        info->pixmap.buf_align = 8;
 
501
        info->pixmap.access_align = 32;
 
502
        info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
503
        info->pixmap.scan_align = 1;
 
504
 
 
505
        DRM_DEBUG("fb depth is %d\n", fb->depth);
 
506
        DRM_DEBUG("   pitch is %d\n", fb->pitch);
 
507
 
 
508
        printk(KERN_INFO"allocated %dx%d fb\n",
 
509
                                psbfb->base.width, psbfb->base.height);
 
510
 
 
511
        mutex_unlock(&dev->struct_mutex);
 
512
 
 
513
        return 0;
 
514
out_err0:
 
515
        fb->funcs->destroy(fb);
 
516
out_err1:
 
517
        mutex_unlock(&dev->struct_mutex);
 
518
        return ret;
 
519
}
 
520
 
 
521
static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
 
522
                                                        u16 blue, int regno)
 
523
{
 
524
        DRM_DEBUG("%s\n", __func__);
 
525
}
 
526
 
 
527
static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
 
528
                                        u16 *green, u16 *blue, int regno)
 
529
{
 
530
        DRM_DEBUG("%s\n", __func__);
 
531
}
 
532
 
 
533
static int psbfb_probe(struct drm_fb_helper *helper,
 
534
                                struct drm_fb_helper_surface_size *sizes)
 
535
{
 
536
        struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
 
537
        int new_fb = 0;
 
538
        int ret;
 
539
 
 
540
        DRM_DEBUG("%s\n", __func__);
 
541
 
 
542
        if (!helper->fb) {
 
543
                ret = psbfb_create(psb_fbdev, sizes);
 
544
                if (ret)
 
545
                        return ret;
 
546
                new_fb = 1;
 
547
        }
 
548
        return new_fb;
 
549
}
 
550
 
 
551
struct drm_fb_helper_funcs psb_fb_helper_funcs = {
 
552
        .gamma_set = psbfb_gamma_set,
 
553
        .gamma_get = psbfb_gamma_get,
 
554
        .fb_probe = psbfb_probe,
 
555
};
 
556
 
 
557
int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 
558
{
 
559
        struct fb_info *info;
 
560
        struct psb_framebuffer *psbfb = fbdev->pfb;
 
561
 
 
562
        if (fbdev->psb_fb_helper.fbdev) {
 
563
                info = fbdev->psb_fb_helper.fbdev;
 
564
                unregister_framebuffer(info);
 
565
                iounmap(info->screen_base);
 
566
                framebuffer_release(info);
 
567
        }
 
568
 
 
569
        drm_fb_helper_fini(&fbdev->psb_fb_helper);
 
570
 
 
571
        drm_framebuffer_cleanup(&psbfb->base);
 
572
 
 
573
        return 0;
 
574
}
 
575
 
 
576
int psb_fbdev_init(struct drm_device *dev)
 
577
{
 
578
        struct psb_fbdev *fbdev;
 
579
        struct drm_psb_private *dev_priv = dev->dev_private;
 
580
        int num_crtc;
 
581
 
 
582
        fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
 
583
        if (!fbdev) {
 
584
                DRM_ERROR("no memory\n");
 
585
                return -ENOMEM;
 
586
        }
 
587
 
 
588
        dev_priv->fbdev = fbdev;
 
589
        fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
 
590
 
 
591
        num_crtc = 2;
 
592
 
 
593
        drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc,
 
594
                                                        INTELFB_CONN_LIMIT);
 
595
 
 
596
        drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
 
597
        drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
 
598
        return 0;
 
599
}
 
600
 
 
601
void psb_fbdev_fini(struct drm_device *dev)
 
602
{
 
603
        struct drm_psb_private *dev_priv = dev->dev_private;
 
604
 
 
605
        if (!dev_priv->fbdev)
 
606
                return;
 
607
 
 
608
        psb_fbdev_destroy(dev, dev_priv->fbdev);
 
609
        kfree(dev_priv->fbdev);
 
610
        dev_priv->fbdev = NULL;
 
611
}
 
612
 
 
613
 
 
614
static void psbfb_output_poll_changed(struct drm_device *dev)
 
615
{
 
616
        struct drm_psb_private *dev_priv = dev->dev_private;
 
617
        struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
 
618
        drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
 
619
}
 
620
 
 
621
int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
 
622
{
 
623
        struct fb_info *info;
 
624
        struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
625
 
 
626
        if (drm_psb_no_fb)
 
627
                return 0;
 
628
 
 
629
        info = psbfb->fbdev;
 
630
        psbfb->pvrBO = NULL;
 
631
 
 
632
        if (info)
 
633
                framebuffer_release(info);
 
634
        return 0;
 
635
}
 
636
/*EXPORT_SYMBOL(psbfb_remove); */
 
637
 
 
638
static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 
639
                                              struct drm_file *file_priv,
 
640
                                              unsigned int *handle)
 
641
{
 
642
        /* JB: TODO currently we can't go from a bo to a handle with ttm */
 
643
        (void) file_priv;
 
644
        *handle = 0;
 
645
        return 0;
 
646
}
 
647
 
 
648
static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
 
649
{
 
650
        struct drm_device *dev = fb->dev;
 
651
        struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
652
 
 
653
        /*ummap gtt pages*/
 
654
        psb_gtt_unmap_meminfo(dev, psbfb->hKernelMemInfo);
 
655
        if (psbfb->fbdev)
 
656
                psbfb_remove(dev, fb);
 
657
 
 
658
        /* JB: TODO not drop, refcount buffer */
 
659
        drm_framebuffer_cleanup(fb);
 
660
        kfree(fb);
 
661
}
 
662
 
 
663
static const struct drm_mode_config_funcs psb_mode_funcs = {
 
664
        .fb_create = psb_user_framebuffer_create,
 
665
        .output_poll_changed = psbfb_output_poll_changed,
 
666
};
 
667
 
 
668
static int psb_create_backlight_property(struct drm_device *dev)
 
669
{
 
670
        struct drm_psb_private *dev_priv
 
671
                                = (struct drm_psb_private *) dev->dev_private;
 
672
        struct drm_property *backlight;
 
673
 
 
674
        if (dev_priv->backlight_property)
 
675
                return 0;
 
676
 
 
677
        backlight = drm_property_create(dev,
 
678
                                        DRM_MODE_PROP_RANGE,
 
679
                                        "backlight",
 
680
                                        2);
 
681
        backlight->values[0] = 0;
 
682
        backlight->values[1] = 100;
 
683
 
 
684
        dev_priv->backlight_property = backlight;
 
685
 
 
686
        return 0;
 
687
}
 
688
 
 
689
static void psb_setup_outputs(struct drm_device *dev)
 
690
{
 
691
        struct drm_psb_private *dev_priv =
 
692
            (struct drm_psb_private *) dev->dev_private;
 
693
        struct drm_connector *connector;
 
694
 
 
695
        PSB_DEBUG_ENTRY("\n");
 
696
 
 
697
        drm_mode_create_scaling_mode_property(dev);
 
698
 
 
699
        psb_create_backlight_property(dev);
 
700
 
 
701
        psb_intel_lvds_init(dev, &dev_priv->mode_dev);
 
702
        /* psb_intel_sdvo_init(dev, SDVOB); */
 
703
 
 
704
        list_for_each_entry(connector, &dev->mode_config.connector_list,
 
705
                            head) {
 
706
                struct psb_intel_output *psb_intel_output =
 
707
                    to_psb_intel_output(connector);
 
708
                struct drm_encoder *encoder = &psb_intel_output->enc;
 
709
                int crtc_mask = 0, clone_mask = 0;
 
710
 
 
711
                /* valid crtcs */
 
712
                switch (psb_intel_output->type) {
 
713
                case INTEL_OUTPUT_SDVO:
 
714
                        crtc_mask = ((1 << 0) | (1 << 1));
 
715
                        clone_mask = (1 << INTEL_OUTPUT_SDVO);
 
716
                        break;
 
717
                case INTEL_OUTPUT_LVDS:
 
718
                        PSB_DEBUG_ENTRY("LVDS.\n");
 
719
                        crtc_mask = (1 << 1);
 
720
                        clone_mask = (1 << INTEL_OUTPUT_LVDS);
 
721
                        break;
 
722
                case INTEL_OUTPUT_MIPI:
 
723
                        PSB_DEBUG_ENTRY("MIPI.\n");
 
724
                        crtc_mask = (1 << 0);
 
725
                        clone_mask = (1 << INTEL_OUTPUT_MIPI);
 
726
                        break;
 
727
                case INTEL_OUTPUT_MIPI2:
 
728
                        PSB_DEBUG_ENTRY("MIPI2.\n");
 
729
                        crtc_mask = (1 << 2);
 
730
                        clone_mask = (1 << INTEL_OUTPUT_MIPI2);
 
731
                        break;
 
732
                case INTEL_OUTPUT_HDMI:
 
733
                        PSB_DEBUG_ENTRY("HDMI.\n");
 
734
                        crtc_mask = (1 << 1);
 
735
                        clone_mask = (1 << INTEL_OUTPUT_HDMI);
 
736
                        break;
 
737
                }
 
738
 
 
739
                encoder->possible_crtcs = crtc_mask;
 
740
                encoder->possible_clones =
 
741
                    psb_intel_connector_clones(dev, clone_mask);
 
742
 
 
743
        }
 
744
}
 
745
 
 
746
static void *psb_bo_from_handle(struct drm_device *dev,
 
747
                                struct drm_file *file_priv,
 
748
                                unsigned int handle)
 
749
{
 
750
        void *psKernelMemInfo = NULL;
 
751
        void * hKernelMemInfo = (void *)handle;
 
752
        int ret;
 
753
 
 
754
        ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
 
755
        if (ret) {
 
756
                DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
 
757
                          (u32)hKernelMemInfo);
 
758
                return NULL;
 
759
        }
 
760
 
 
761
        return (void *)psKernelMemInfo;
 
762
}
 
763
 
 
764
static size_t psb_bo_size(struct drm_device *dev, void *bof)
 
765
{
 
766
#if 0
 
767
        void *psKernelMemInfo   = (void *)bof;
 
768
        return (size_t)psKernelMemInfo->ui32AllocSize;
 
769
#else
 
770
        return 0;
 
771
#endif
 
772
}
 
773
 
 
774
static size_t psb_bo_offset(struct drm_device *dev, void *bof)
 
775
{
 
776
        struct psb_framebuffer *psbfb
 
777
                = (struct psb_framebuffer *)bof;
 
778
 
 
779
        return (size_t)psbfb->offset;
 
780
}
 
781
 
 
782
static int psb_bo_pin_for_scanout(struct drm_device *dev, void *bo)
 
783
{
 
784
         return 0;
 
785
}
 
786
 
 
787
static int psb_bo_unpin_for_scanout(struct drm_device *dev, void *bo)
 
788
{
 
789
        return 0;
 
790
}
 
791
 
 
792
void psb_modeset_init(struct drm_device *dev)
 
793
{
 
794
        struct drm_psb_private *dev_priv =
 
795
            (struct drm_psb_private *) dev->dev_private;
 
796
        struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
 
797
        int i;
 
798
 
 
799
        PSB_DEBUG_ENTRY("\n");
 
800
        /* Init mm functions */
 
801
        mode_dev->bo_from_handle = psb_bo_from_handle;
 
802
        mode_dev->bo_size = psb_bo_size;
 
803
        mode_dev->bo_offset = psb_bo_offset;
 
804
        mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout;
 
805
        mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout;
 
806
 
 
807
        drm_mode_config_init(dev);
 
808
 
 
809
        dev->mode_config.min_width = 0;
 
810
        dev->mode_config.min_height = 0;
 
811
 
 
812
        dev->mode_config.funcs = (void *) &psb_mode_funcs;
 
813
 
 
814
        /* set memory base */
 
815
        /* MRST and PSB should use BAR 2*/
 
816
        pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
 
817
                                        &(dev->mode_config.fb_base));
 
818
 
 
819
        /* num pipes is 2 for PSB but 1 for Mrst */
 
820
        for (i = 0; i < dev_priv->num_pipe; i++)
 
821
                psb_intel_crtc_init(dev, i, mode_dev);
 
822
 
 
823
        dev->mode_config.max_width = 2048;
 
824
        dev->mode_config.max_height = 2048;
 
825
 
 
826
        psb_setup_outputs(dev);
 
827
 
 
828
        /* setup fbs */
 
829
        /* drm_initial_config(dev); */
 
830
}
 
831
 
 
832
void psb_modeset_cleanup(struct drm_device *dev)
 
833
{
 
834
        mutex_lock(&dev->struct_mutex);
 
835
 
 
836
        drm_kms_helper_poll_fini(dev);
 
837
        psb_fbdev_fini(dev);
 
838
 
 
839
        drm_mode_config_cleanup(dev);
 
840
 
 
841
        mutex_unlock(&dev->struct_mutex);
 
842
}