Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /**************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2007-2011, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  **************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/pfn_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <drm/drm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <drm/drm_crtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <drm/drm_fb_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <drm/drm_fourcc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <drm/drm_gem_framebuffer_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "framebuffer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include "gtt.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include "psb_drv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include "psb_intel_drv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include "psb_intel_reg.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static const struct drm_framebuffer_funcs psb_fb_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	.destroy = drm_gem_fb_destroy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	.create_handle = drm_gem_fb_create_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 			   unsigned blue, unsigned transp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			   struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct drm_fb_helper *fb_helper = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct drm_framebuffer *fb = fb_helper->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	uint32_t v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (!fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (regno > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	red = CMAP_TOHW(red, info->var.red.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	blue = CMAP_TOHW(blue, info->var.blue.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	green = CMAP_TOHW(green, info->var.green.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	transp = CMAP_TOHW(transp, info->var.transp.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	v = (red << info->var.red.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	    (green << info->var.green.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	    (blue << info->var.blue.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	    (transp << info->var.transp.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	if (regno < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		switch (fb->format->cpp[0] * 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 			((uint32_t *) info->pseudo_palette)[regno] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			((uint32_t *) info->pseudo_palette)[regno] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	struct drm_fb_helper *fb_helper = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct drm_framebuffer *fb = fb_helper->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	struct drm_device *dev = fb->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	struct gtt_range *gtt = to_gtt_range(fb->obj[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 *	We have to poke our nose in here. The core fb code assumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 *	panning is part of the hardware that can be invoked before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 *	the actual fb is mapped. In our case that isn't quite true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (gtt->npage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		/* GTT roll shifts in 4K pages, we need to shift the right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		   number of pages */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		int pages = info->fix.line_length >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		psb_gtt_roll(dev, gtt, var->yoffset * pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)         return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	struct vm_area_struct *vma = vmf->vma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	struct drm_framebuffer *fb = vma->vm_private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	struct drm_device *dev = fb->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct gtt_range *gtt = to_gtt_range(fb->obj[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	int page_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	unsigned long address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	vm_fault_t ret = VM_FAULT_SIGBUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	unsigned long pfn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				  gtt->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	page_num = vma_pages(vma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	address = vmf->address - (vmf->pgoff << PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	for (i = 0; i < page_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		pfn = (phys_addr >> PAGE_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		ret = vmf_insert_mixed(vma, address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 				__pfn_to_pfn_t(pfn, PFN_DEV));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		if (unlikely(ret & VM_FAULT_ERROR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		address += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		phys_addr += PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static void psbfb_vm_open(struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static void psbfb_vm_close(struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static const struct vm_operations_struct psbfb_vm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	.fault	= psbfb_vm_fault,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	.open	= psbfb_vm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	.close	= psbfb_vm_close
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	struct drm_fb_helper *fb_helper = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	struct drm_framebuffer *fb = fb_helper->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	if (vma->vm_pgoff != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	 * If this is a GEM object then info->screen_base is the virtual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	 * kernel remapping of the object. FIXME: Review if this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	 * suitable for our mmap work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	vma->vm_ops = &psbfb_vm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	vma->vm_private_data = (void *)fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static const struct fb_ops psbfb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	DRM_FB_HELPER_DEFAULT_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	.fb_setcolreg = psbfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	.fb_copyarea = psbfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	.fb_mmap = psbfb_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	.fb_sync = psbfb_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static const struct fb_ops psbfb_roll_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	DRM_FB_HELPER_DEFAULT_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	.fb_setcolreg = psbfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	.fb_pan_display = psbfb_pan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	.fb_mmap = psbfb_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static const struct fb_ops psbfb_unaccel_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	DRM_FB_HELPER_DEFAULT_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	.fb_setcolreg = psbfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	.fb_mmap = psbfb_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  *	psb_framebuffer_init	-	initialize a framebuffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  *	@dev: our DRM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  *	@fb: framebuffer to set up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  *	@mode_cmd: mode description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  *	@gt: backing object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  *	Configure and fill in the boilerplate for our frame buffer. Return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  *	0 on success or an error code if we fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static int psb_framebuffer_init(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 					struct drm_framebuffer *fb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 					const struct drm_mode_fb_cmd2 *mode_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 					struct drm_gem_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	const struct drm_format_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	 * Reject unknown formats, YUV formats, and formats with more than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	 * 4 bytes per pixel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	info = drm_get_format_info(dev, mode_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (!info || !info->depth || info->cpp[0] > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	if (mode_cmd->pitches[0] & 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	fb->obj[0] = obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	ret = drm_framebuffer_init(dev, fb, &psb_fb_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  *	psb_framebuffer_create	-	create a framebuffer backed by gt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  *	@dev: our DRM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  *	@mode_cmd: the description of the requested mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  *	@gt: the backing object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  *	Create a framebuffer object backed by the gt, and fill in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  *	boilerplate required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)  *	TODO: review object references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static struct drm_framebuffer *psb_framebuffer_create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			 const struct drm_mode_fb_cmd2 *mode_cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 			 struct drm_gem_object *obj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	struct drm_framebuffer *fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	if (!fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	ret = psb_framebuffer_init(dev, fb, mode_cmd, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		kfree(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	return fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)  *	psbfb_alloc		-	allocate frame buffer memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)  *	@dev: the DRM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  *	@aligned_size: space needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  *	Allocate the frame buffer. In the usual case we get a GTT range that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  *	is stolen memory backed and life is simple. If there isn't sufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  *	we fail as we don't have the virtual mapping space to really vmap it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  *	and the kernel console code can't handle non linear framebuffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  *	Re-address this as and if the framebuffer layer grows this ability.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	struct gtt_range *backing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	/* Begin by trying to use stolen memory backing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	if (backing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		drm_gem_private_object_init(dev, &backing->gem, aligned_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		return backing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  *	psbfb_create		-	create a framebuffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  *	@fbdev: the framebuffer device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  *	@sizes: specification of the layout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)  *	Create a framebuffer to the specifications provided
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static int psbfb_create(struct drm_fb_helper *fb_helper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 				struct drm_fb_helper_surface_size *sizes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	struct drm_device *dev = fb_helper->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	struct drm_framebuffer *fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	struct drm_mode_fb_cmd2 mode_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	struct gtt_range *backing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	u32 bpp, depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	int gtt_roll = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	int pitch_lines = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	mode_cmd.width = sizes->surface_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	mode_cmd.height = sizes->surface_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	bpp = sizes->surface_bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	depth = sizes->surface_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	/* No 24bit packed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	if (bpp == 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		bpp = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		 * Acceleration via the GTT requires pitch to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		 * power of two aligned. Preferably page but less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		 * is ok with some fonts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)         	mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)         	size = mode_cmd.pitches[0] * mode_cmd.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)         	size = ALIGN(size, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		/* Allocate the fb in the GTT with stolen page backing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		backing = psbfb_alloc(dev, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		if (pitch_lines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 			pitch_lines *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 			pitch_lines = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		gtt_roll++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	} while (backing == NULL && pitch_lines <= 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	/* The final pitch we accepted if we succeeded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	pitch_lines /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	if (backing == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		 *	We couldn't get the space we wanted, fall back to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		 *	display engine requirement instead.  The HW requires
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		 *	the pitch to be 64 byte aligned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		gtt_roll = 0;	/* Don't use GTT accelerated scrolling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		pitch_lines = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		size = mode_cmd.pitches[0] * mode_cmd.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		size = ALIGN(size, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		/* Allocate the framebuffer in the GTT with stolen page backing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		backing = psbfb_alloc(dev, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		if (backing == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	memset(dev_priv->vram_addr + backing->offset, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	info = drm_fb_helper_alloc_fbi(fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (IS_ERR(info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		ret = PTR_ERR(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	fb = psb_framebuffer_create(dev, &mode_cmd, &backing->gem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	if (IS_ERR(fb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		ret = PTR_ERR(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	fb_helper->fb = fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	if (dev_priv->ops->accel_2d && pitch_lines > 8)	/* 2D engine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		info->fbops = &psbfb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	else if (gtt_roll) {	/* GTT rolling seems best */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		info->fbops = &psbfb_roll_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		info->flags |= FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	} else	/* Software */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 		info->fbops = &psbfb_unaccel_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	info->fix.smem_start = dev->mode_config.fb_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	info->fix.smem_len = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	info->fix.ywrapstep = gtt_roll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	info->fix.ypanstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	/* Accessed stolen memory directly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	info->screen_base = dev_priv->vram_addr + backing->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	info->screen_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (dev_priv->gtt.stolen_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		info->apertures->ranges[0].base = dev->mode_config.fb_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	drm_fb_helper_fill_info(info, fb_helper, sizes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	psb_gtt_free_range(dev, backing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)  *	psb_user_framebuffer_create	-	create framebuffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)  *	@dev: our DRM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)  *	@filp: client file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  *	@cmd: mode request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  *	Create a new framebuffer backed by a userspace GEM object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static struct drm_framebuffer *psb_user_framebuffer_create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 			(struct drm_device *dev, struct drm_file *filp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			 const struct drm_mode_fb_cmd2 *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	struct drm_gem_object *obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	struct drm_framebuffer *fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	 *	Find the GEM object and thus the gtt range object that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	 *	to back this space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	obj = drm_gem_object_lookup(filp, cmd->handles[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	if (obj == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	/* Let the core code do all the work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	fb = psb_framebuffer_create(dev, cmd, obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	if (IS_ERR(fb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		drm_gem_object_put(obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	return fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int psbfb_probe(struct drm_fb_helper *fb_helper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 				struct drm_fb_helper_surface_size *sizes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	struct drm_device *dev = fb_helper->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	unsigned int fb_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	int bytespp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	bytespp = sizes->surface_bpp / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	if (bytespp == 3)	/* no 24bit packed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		bytespp = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	/* If the mode will not fit in 32bit then switch to 16bit to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	   a console on full resolution. The X mode setting server will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	   allocate its own 32bit GEM framebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	fb_size = ALIGN(sizes->surface_width * bytespp, 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		  sizes->surface_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	fb_size = ALIGN(fb_size, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	if (fb_size > dev_priv->vram_stolen_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)                 sizes->surface_bpp = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)                 sizes->surface_depth = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	return psbfb_create(fb_helper, sizes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	.fb_probe = psbfb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) static int psb_fbdev_destroy(struct drm_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 			     struct drm_fb_helper *fb_helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	struct drm_framebuffer *fb = fb_helper->fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	drm_fb_helper_unregister_fbi(fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	drm_fb_helper_fini(fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	drm_framebuffer_unregister_private(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	drm_framebuffer_cleanup(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	if (fb->obj[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		drm_gem_object_put(fb->obj[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	kfree(fb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) int psb_fbdev_init(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	struct drm_fb_helper *fb_helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	if (!fb_helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		dev_err(dev->dev, "no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	dev_priv->fb_helper = fb_helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	drm_fb_helper_prepare(dev, fb_helper, &psb_fb_helper_funcs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	ret = drm_fb_helper_init(dev, fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	/* disable all the possible outputs/crtcs before entering KMS mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	drm_helper_disable_unused_functions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	ret = drm_fb_helper_initial_config(fb_helper, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		goto fini;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) fini:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	drm_fb_helper_fini(fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	kfree(fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static void psb_fbdev_fini(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	if (!dev_priv->fb_helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	psb_fbdev_destroy(dev, dev_priv->fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	kfree(dev_priv->fb_helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	dev_priv->fb_helper = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static const struct drm_mode_config_funcs psb_mode_funcs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	.fb_create = psb_user_framebuffer_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	.output_poll_changed = drm_fb_helper_output_poll_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static void psb_setup_outputs(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	struct drm_connector *connector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	drm_mode_create_scaling_mode_property(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	/* It is ok for this to fail - we just don't get backlight control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	if (!dev_priv->backlight_property)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		dev_priv->backlight_property = drm_property_create_range(dev, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 							"backlight", 0, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	dev_priv->ops->output_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	list_for_each_entry(connector, &dev->mode_config.connector_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 			    head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		struct gma_encoder *gma_encoder = gma_attached_encoder(connector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 		struct drm_encoder *encoder = &gma_encoder->base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		int crtc_mask = 0, clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		/* valid crtcs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		switch (gma_encoder->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		case INTEL_OUTPUT_ANALOG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			crtc_mask = (1 << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 			clone_mask = (1 << INTEL_OUTPUT_ANALOG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		case INTEL_OUTPUT_SDVO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			crtc_mask = dev_priv->ops->sdvo_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		case INTEL_OUTPUT_LVDS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 			crtc_mask = dev_priv->ops->lvds_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 			clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		case INTEL_OUTPUT_MIPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 			crtc_mask = (1 << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 			clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		case INTEL_OUTPUT_MIPI2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 			crtc_mask = (1 << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 			clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		case INTEL_OUTPUT_HDMI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 			crtc_mask = dev_priv->ops->hdmi_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			clone_mask = (1 << INTEL_OUTPUT_HDMI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		case INTEL_OUTPUT_DISPLAYPORT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 			crtc_mask = (1 << 0) | (1 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 			clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 		case INTEL_OUTPUT_EDP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 			crtc_mask = (1 << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 			clone_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 		encoder->possible_crtcs = crtc_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		encoder->possible_clones =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		    gma_connector_clones(dev, clone_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) void psb_modeset_init(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	drm_mode_config_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	dev->mode_config.min_width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	dev->mode_config.min_height = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	dev->mode_config.funcs = &psb_mode_funcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	/* set memory base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	/* Oaktrail and Poulsbo should use BAR 2*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 					&(dev->mode_config.fb_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	/* num pipes is 2 for PSB but 1 for Mrst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	for (i = 0; i < dev_priv->num_pipe; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		psb_intel_crtc_init(dev, i, mode_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	dev->mode_config.max_width = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	dev->mode_config.max_height = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	psb_setup_outputs(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	if (dev_priv->ops->errata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	        dev_priv->ops->errata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)         dev_priv->modeset = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) void psb_modeset_cleanup(struct drm_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	struct drm_psb_private *dev_priv = dev->dev_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	if (dev_priv->modeset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 		drm_kms_helper_poll_fini(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		psb_fbdev_fini(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 		drm_mode_config_cleanup(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }