summaryrefslogtreecommitdiff
path: root/linux-core
ModeNameSize
-rw-r--r--Config.in594logplain
-rw-r--r--Doxyfile41652logplain
-rw-r--r--Kconfig3476logplain
-rw-r--r--Makefile10539logplain
-rw-r--r--Makefile.kernel2880logplain
-rw-r--r--README.drm1850logplain
-rw-r--r--ati_pcigart.c5407logplain
-rw-r--r--drmP.h35328logplain
-rw-r--r--drm_agpsupport.c13240logplain
-rw-r--r--drm_auth.c6295logplain
-rw-r--r--drm_bufs.c34951logplain
-rw-r--r--drm_context.c15265logplain
-rw-r--r--drm_dma.c5913logplain
-rw-r--r--drm_drawable.c1959logplain
-rw-r--r--drm_drv.c33999logplain
-rw-r--r--drm_fops.c4207logplain
-rw-r--r--drm_init.c3796logplain
-rw-r--r--drm_ioctl.c9229logplain
-rw-r--r--drm_irq.c9682logplain
-rw-r--r--drm_lock.c4871logplain
-rw-r--r--drm_memory.h9464logplain
-rw-r--r--drm_memory_debug.h12305logplain
-rw-r--r--drm_os_linux.h4803logplain
-rw-r--r--drm_pci.c4574logplain
-rw-r--r--drm_proc.c15405logplain
-rw-r--r--drm_scatter.c5964logplain
-rw-r--r--drm_stub.c6750logplain
-rw-r--r--drm_vm.c18821logplain
-rw-r--r--ffb.h282logplain
-rw-r--r--ffb_context.c17484logplain
-rw-r--r--ffb_drv.c9621logplain
-rw-r--r--ffb_drv.h10783logplain
-rw-r--r--i810_dma.c37301logplain
-rw-r--r--i810_drm.h9370logplain
-rw-r--r--i810_drv.c2006logplain
-rw-r--r--i810_drv.h8713logplain
-rw-r--r--i830_dma.c41361logplain
-rw-r--r--i830_drm.h10879logplain
-rw-r--r--i830_drv.c2121logplain
-rw-r--r--i830_drv.h10065logplain
-rw-r--r--i830_irq.c5631logplain
-rw-r--r--i915_drv.c837logplain
-rw-r--r--mach64_drv.c1887logplain
-rw-r--r--mga_drv.c1989logplain
-rw-r--r--r128_drv.c2036logplain
-rw-r--r--radeon_drv.c1857logplain
-rw-r--r--savage.h1519logplain
-rw-r--r--savage_dma.c1564logplain
-rw-r--r--savage_drm.h7224logplain
-rw-r--r--savage_drv.c7932logplain
-rw-r--r--savage_drv.h1343logplain
-rw-r--r--sis_drv.c1765logplain
-rw-r--r--tdfx_drv.c1912logplain
/a> 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769
/*
 * Copyright © 2007 David Airlie
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *     David Airlie
 */
    /*
     *  Modularization
     */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>

#include "drmP.h"
#include "drm.h"
#include "drm_crtc.h"
#include "i915_drm.h"
#include "i915_drv.h"

struct intelfb_par {
	struct drm_device *dev;
	struct drm_crtc *crtc;
        struct drm_display_mode *fb_mode;
	struct drm_framebuffer *fb;
};
/*
static int
var_to_refresh(const struct fb_var_screeninfo *var)
{
	int xtot = var->xres + var->left_margin + var->right_margin +
		   var->hsync_len;
	int ytot = var->yres + var->upper_margin + var->lower_margin +
		   var->vsync_len;

	return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
}*/

static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
			   unsigned blue, unsigned transp,
			   struct fb_info *info)
{
	struct intelfb_par *par = info->par;
	struct drm_framebuffer *fb = par->fb;
	struct drm_crtc *crtc = par->crtc;

	if (regno > 255)
		return 1;

	if (fb->depth == 8) {
		if (crtc->funcs->gamma_set)
			crtc->funcs->gamma_set(crtc, red, green, blue, regno);
		return 0;
	}

	if (regno < 16) {
		switch (fb->depth) {
		case 15:
			fb->pseudo_palette[regno] = ((red & 0xf800) >>  1) |
				((green & 0xf800) >>  6) |
				((blue & 0xf800) >> 11);
			break;
		case 16:
			fb->pseudo_palette[regno] = (red & 0xf800) |
				((green & 0xfc00) >>  5) |
				((blue  & 0xf800) >> 11);
			break;
		case 24:
		case 32:
			fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
				(green & 0xff00) |
				((blue  & 0xff00) >> 8);
			break;
		}
	}

	return 0;
}

static int intelfb_check_var(struct fb_var_screeninfo *var,
			     struct fb_info *info)
{
        struct intelfb_par *par = info->par;
        /*struct drm_device *dev = par->dev;*/
	struct drm_framebuffer *fb = par->fb;
        /*struct drm_output *output;*/
        int depth/*, found = 0*/;

        if (!var->pixclock)
                return -EINVAL;

        /* Need to resize the fb object !!! */
        if (var->xres > fb->width || var->yres > fb->height) {
                DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height);
                DRM_ERROR("Need resizing code.\n");
                return -EINVAL;
        }

        switch (var->bits_per_pixel) {
        case 16:
                depth = (var->green.length == 6) ? 16 : 15;
                break;
        case 32:
                depth = (var->transp.length > 0) ? 32 : 24;
                break;
        default:
                depth = var->bits_per_pixel;
                break;
        }
                
        switch (depth) {
        case 8:
                var->red.offset = 0;
                var->green.offset = 0;
                var->blue.offset = 0;
                var->red.length = 8;
                var->green.length = 8;
                var->blue.length = 8;
                var->transp.length = 0;
                var->transp.offset = 0;
                break;
        case 15:
                var->red.offset = 10;
                var->green.offset = 5;
                var->blue.offset = 0;
                var->red.length = 5;
                var->green.length = 5;
                var->blue.length = 5;
                var->transp.length = 1;
                var->transp.offset = 15;
                break;
        case 16:
                var->red.offset = 11;
                var->green.offset = 5;
                var->blue.offset = 0;
                var->red.length = 5;
                var->green.length = 6;
                var->blue.length = 5;
                var->transp.length = 0;
                var->transp.offset = 0;
                break;
        case 24:
                var->red.offset = 16;
                var->green.offset = 8;
                var->blue.offset = 0;
                var->red.length = 8;
                var->green.length = 8;
                var->blue.length = 8;
                var->transp.length = 0;
                var->transp.offset = 0;
                break;
        case 32:
                var->red.offset = 16;
                var->green.offset = 8;
                var->blue.offset = 0;
                var->red.length = 8;
                var->green.length = 8;
                var->blue.length = 8;
                var->transp.length = 8;
                var->transp.offset = 24;
                break;
        default:
                return -EINVAL; 
        }

#if 0
        /* Here we walk the output mode list and look for modes. If we haven't
         * got it, then bail. Not very nice, so this is disabled.
         * In the set_par code, we create our mode based on the incoming
         * parameters. Nicer, but may not be desired by some.
         */
        list_for_each_entry(output, &dev->mode_config.output_list, head) {
                if (output->crtc == par->crtc)
                        break;
        }
    
        list_for_each_entry(drm_mode, &output->modes, head) {
                if (drm_mode->hdisplay == var->xres &&
                    drm_mode->vdisplay == var->yres &&
                    (((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) &&
                    (((PICOS2KHZ(var->pixclock))/1000) <= ((drm_mode->clock/1000)+1))) {
			found = 1;
			break;
		}
	}
 
        if (!found)
                return -EINVAL;
#endif

	return 0;
}

/* this will let fbcon do the mode init */
/* FIXME: take mode config lock? */
static int intelfb_set_par(struct fb_info *info)
{
	struct intelfb_par *par = info->par;
	struct drm_framebuffer *fb = par->fb;
	struct drm_device *dev = par->dev;
        struct drm_display_mode *drm_mode, *search_mode;
        struct drm_output *output = NULL;
        struct fb_var_screeninfo *var = &info->var;
	int found = 0;
	int changed = 0;

	DRM_DEBUG("\n");

        switch (var->bits_per_pixel) {
        case 16:
                fb->depth = (var->green.length == 6) ? 16 : 15;
                break;
        case 32:
                fb->depth = (var->transp.length > 0) ? 32 : 24;
                break;
        default:
                fb->depth = var->bits_per_pixel;
                break;
        }

        fb->bits_per_pixel = var->bits_per_pixel;

        info->fix.line_length = fb->pitch;
        info->fix.smem_len = info->fix.line_length * fb->height;
        info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;

        info->screen_size = info->fix.smem_len; /* ??? */

	/* create a drm mode */
        drm_mode = drm_mode_create(dev);
        drm_mode->hdisplay = var->xres;
        drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin;
        drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len;
        drm_mode->htotal = drm_mode->hsync_end + var->left_margin;
        drm_mode->vdisplay = var->yres;
        drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin;
        drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len;
        drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin;
        drm_mode->clock = PICOS2KHZ(var->pixclock);
        drm_mode->vrefresh = drm_mode_vrefresh(drm_mode);
	drm_mode->flags = 0;
	drm_mode->flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC;
	drm_mode->flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC;

        drm_mode_set_name(drm_mode);
	drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);

	found = 0;
        list_for_each_entry(output, &dev->mode_config.output_list, head) {
                if (output->crtc == par->crtc){
			found = 1;
                        break;
		}
        }

	/* no output bound, bail */
	if (!found)
		return -EINVAL;

	found = 0;
	drm_mode_debug_printmodeline(dev, drm_mode);    
        list_for_each_entry(search_mode, &output->modes, head) {
		drm_mode_debug_printmodeline(dev, search_mode);
		if (drm_mode_equal(drm_mode, search_mode)) {
			drm_mode_destroy(dev, drm_mode);
			drm_mode = search_mode;
			found = 1;
			break;
		}
	}
	
	/* If we didn't find a matching mode that exists on our output,
	 * create a new attachment for the incoming user specified mode
	 */
	if (!found) {
		if (par->fb_mode) {
			/* this also destroys the mode */
			drm_mode_detachmode_crtc(dev, par->fb_mode);
		}
	
		par->fb_mode = drm_mode;
		drm_mode_debug_printmodeline(dev, drm_mode);
		/* attach mode */
		drm_mode_attachmode_crtc(dev, par->crtc, par->fb_mode);
	}

	/* re-attach fb */
	if (!par->crtc->fb) {
		par->crtc->fb = par->fb;