Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db1a19b3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'intelfb-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/intelfb-2.6

* 'intelfb-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/intelfb-2.6:
  intelfbhw.c: intelfbhw_get_p1p2 defined but not used
  intelfb: fix mtrr_reg signedness
  intelfb: update doc and Kconfig (supported devices)
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add preliminary i2c support
  intelfb: add vsync interrupt support
  intelfb: add vsync interrupt support
  intelfb: add vsync interrupt support
  intelfb: add vsync interrupt support
  intelfb: add vsync interrupt support
parents 369aa839 4dc3595f
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
Intel 830M/845G/852GM/855GM/865G/915G Framebuffer driver
Intel 830M/845G/852GM/855GM/865G/915G/945G Framebuffer driver
================================================================

A. Introduction
	This is a framebuffer driver for various Intel 810/815 compatible
	This is a framebuffer driver for various Intel 8xx/9xx compatible
graphics devices.  These would include:

	Intel 830M
	Intel 810E845G
	Intel 845G
	Intel 852GM
	Intel 855GM
	Intel 865G
	Intel 915G
	Intel 915GM
	Intel 945G
	Intel 945GM

B.  List of available options

@@ -78,7 +81,7 @@ C. Kernel booting
Separate each option/option-pair by commas (,) and the option from its value
with an equals sign (=) as in the following:

video=i810fb:option1,option2=value2
video=intelfb:option1,option2=value2

Sample Usage
------------
+22 −4
Original line number Diff line number Diff line
@@ -825,22 +825,33 @@ config FB_I810_I2C
	help

config FB_INTEL
	tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
	tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
	depends on FB && EXPERIMENTAL && PCI && X86
	select AGP
	select AGP_INTEL
	select I2C_ALGOBIT if FB_INTEL_I2C
	select I2C if FB_INTEL_I2C
	select FB_MODE_HELPERS
	select FB_CFB_FILLRECT
	select FB_CFB_COPYAREA
	select FB_CFB_IMAGEBLIT
	help
	  This driver supports the on-board graphics built in to the Intel
          830M/845G/852GM/855GM/865G chipsets.
          830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM chipsets.
          Say Y if you have and plan to use such a board.

	  If you say Y here and want DDC/I2C support you must first say Y to
	  "I2C support" and "I2C bit-banging support" in the character devices
	  section.

	  If you say M here then "I2C support" and "I2C bit-banging support"
	  can be build either as modules or built-in.

	  To compile this driver as a module, choose M here: the
	  module will be called intelfb.

	  For more information, please read <file:Documentation/fb/intelfb.txt>

config FB_INTEL_DEBUG
	bool "Intel driver Debug Messages"
	depends on FB_INTEL
@@ -849,6 +860,13 @@ config FB_INTEL_DEBUG
	  of debugging informations to provide to the maintainer when
	  something goes wrong.

config FB_INTEL_I2C
	bool "DDC/I2C for Intel framebuffer support"
	depends on FB_INTEL
	default y
	help
	  Say Y here if you want DDC/I2C support for your on-board Intel graphics.

config FB_MATROX
	tristate "Matrox acceleration"
	depends on FB && PCI
+3 −1
Original line number Diff line number Diff line
obj-$(CONFIG_FB_INTEL) += intelfb.o

intelfb-objs := intelfbdrv.o intelfbhw.o
intelfb-y := intelfbdrv.o intelfbhw.o
intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
intelfb-objs := $(intelfb-y)

ifdef CONFIG_FB_INTEL_DEBUG
#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
+78 −1
Original line number Diff line number Diff line
@@ -6,6 +6,10 @@
#include <linux/agp_backend.h>
#include <linux/fb.h>

#ifdef CONFIG_FB_INTEL_I2C
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#endif

/*** Version/name ***/
#define INTELFB_VERSION			"0.9.4"
@@ -115,6 +119,29 @@
/* Intel agpgart driver */
#define AGP_PHYSICAL_MEMORY     2

/* store information about an Ixxx DVO */
/* The i830->i865 use multiple DVOs with multiple i2cs */
/* the i915, i945 have a single sDVO i2c bus - which is different */
#define MAX_OUTPUTS 6

/* these are outputs from the chip - integrated only
   external chips are via DVO or SDVO output */
#define INTELFB_OUTPUT_UNUSED 0
#define INTELFB_OUTPUT_ANALOG 1
#define INTELFB_OUTPUT_DVO 2
#define INTELFB_OUTPUT_SDVO 3
#define INTELFB_OUTPUT_LVDS 4
#define INTELFB_OUTPUT_TVOUT 5

#define INTELFB_DVO_CHIP_NONE 0
#define INTELFB_DVO_CHIP_LVDS 1
#define INTELFB_DVO_CHIP_TMDS 2
#define INTELFB_DVO_CHIP_TVOUT 4

#define INTELFB_OUTPUT_PIPE_NC  0
#define INTELFB_OUTPUT_PIPE_A   1
#define INTELFB_OUTPUT_PIPE_B   2

/*** Data Types ***/

/* supported chipsets */
@@ -195,6 +222,10 @@ struct intelfb_hwstate {
	u32 mem_mode;
	u32 fw_blc_0;
	u32 fw_blc_1;
	u16 hwstam;
	u16 ier;
	u16 iir;
	u16 imr;
};

struct intelfb_heap_data {
@@ -204,6 +235,33 @@ struct intelfb_heap_data {
	u32 size;    // in bytes
};

#ifdef CONFIG_FB_INTEL_I2C
struct intelfb_i2c_chan {
    struct intelfb_info *dinfo;
    u32 reg;
    struct i2c_adapter adapter;
    struct i2c_algo_bit_data algo;
};
#endif

struct intelfb_output_rec {
    int type;
    int pipe;
    int flags;

#ifdef CONFIG_FB_INTEL_I2C
    struct intelfb_i2c_chan i2c_bus;
    struct intelfb_i2c_chan ddc_bus;
#endif
};

struct intelfb_vsync {
	wait_queue_head_t wait;
	unsigned int count;
	int pan_display;
	u32 pan_offset;
};

struct intelfb_info {
	struct fb_info *info;
	struct fb_ops  *fbops;
@@ -220,7 +278,7 @@ struct intelfb_info {
	u8 fbmem_gart;

	/* mtrr support */
	u32 mtrr_reg;
	int mtrr_reg;
	u32 has_mtrr;

	/* heap data */
@@ -267,6 +325,12 @@ struct intelfb_info {
	int fixed_mode;
	int ring_active;
	int flag;
	unsigned long irq_flags;
	int open;

	/* vsync */
	struct intelfb_vsync vsync;
	spinlock_t int_lock;

	/* hw cursor */
	int cursor_on;
@@ -285,12 +349,25 @@ struct intelfb_info {
	
	/* index into plls */
	int pll_index;

	/* outputs */
	int num_outputs;
	struct intelfb_output_rec output[MAX_OUTPUTS];
};

#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM))

#ifndef FBIO_WAITFORVSYNC
#define FBIO_WAITFORVSYNC	_IOW('F', 0x20, __u32)
#endif

/*** function prototypes ***/

extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);

#ifdef CONFIG_FB_INTEL_I2C
extern void intelfb_create_i2c_busses(struct intelfb_info *dinfo);
extern void intelfb_delete_i2c_busses(struct intelfb_info *dinfo);
#endif

#endif /* _INTELFB_H */
+200 −0
Original line number Diff line number Diff line
/**************************************************************************

 Copyright 2006 Dave Airlie <airlied@linux.ie>

All Rights Reserved.

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
on the rights to use, copy, modify, merge, publish, distribute, sub
license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL
THE COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.

**************************************************************************/

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/fb.h>

#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h>

#include <asm/io.h>

#include "intelfb.h"
#include "intelfbhw.h"

/* bit locations in the registers */
#define SCL_DIR_MASK		0x0001
#define SCL_DIR			0x0002
#define SCL_VAL_MASK		0x0004
#define SCL_VAL_OUT		0x0008
#define SCL_VAL_IN		0x0010
#define SDA_DIR_MASK		0x0100
#define SDA_DIR			0x0200
#define SDA_VAL_MASK		0x0400
#define SDA_VAL_OUT		0x0800
#define SDA_VAL_IN		0x1000

static void intelfb_gpio_setscl(void *data, int state)
{
	struct intelfb_i2c_chan *chan = data;
	struct intelfb_info *dinfo = chan->dinfo;
	u32 val;

	OUTREG(chan->reg, (state ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK);
	val = INREG(chan->reg);
}

static void intelfb_gpio_setsda(void *data, int state)
{
	struct intelfb_i2c_chan *chan = data;
	struct intelfb_info *dinfo = chan->dinfo;
	u32 val;

	OUTREG(chan->reg, (state ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK);
	val = INREG(chan->reg);
}

static int intelfb_gpio_getscl(void *data)
{
	struct intelfb_i2c_chan *chan = data;
	struct intelfb_info *dinfo = chan->dinfo;
	u32 val;

	OUTREG(chan->reg, SCL_DIR_MASK);
	OUTREG(chan->reg, 0);
	val = INREG(chan->reg);
	return ((val & SCL_VAL_IN) != 0);
}

static int intelfb_gpio_getsda(void *data)
{
	struct intelfb_i2c_chan *chan = data;
	struct intelfb_info *dinfo = chan->dinfo;
	u32 val;

	OUTREG(chan->reg, SDA_DIR_MASK);
	OUTREG(chan->reg, 0);
	val = INREG(chan->reg);
	return ((val & SDA_VAL_IN) != 0);
}

static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
								 struct intelfb_i2c_chan *chan,
								 const u32 reg, const char *name)
{
	int rc;

	chan->dinfo					= dinfo;
	chan->reg					= reg;
	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name);
	chan->adapter.owner			= THIS_MODULE;
	chan->adapter.id			= I2C_HW_B_INTELFB;
	chan->adapter.algo_data		= &chan->algo;
	chan->adapter.dev.parent	= &chan->dinfo->pdev->dev;
	chan->algo.setsda			= intelfb_gpio_setsda;
	chan->algo.setscl			= intelfb_gpio_setscl;
	chan->algo.getsda			= intelfb_gpio_getsda;
	chan->algo.getscl			= intelfb_gpio_getscl;
	chan->algo.udelay			= 40;
	chan->algo.timeout			= 20;
	chan->algo.data				= chan;

	i2c_set_adapdata(&chan->adapter, chan);

	/* Raise SCL and SDA */
	intelfb_gpio_setsda(chan, 1);
	intelfb_gpio_setscl(chan, 1);
	udelay(20);

	rc = i2c_bit_add_bus(&chan->adapter);
	if (rc == 0)
		DBG_MSG("I2C bus %s registered.\n", name);
	else
		WRN_MSG("Failed to register I2C bus %s.\n", name);
	return rc;
}

void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
{
	int i = 0;

	/* everyone has at least a single analog output */
	dinfo->num_outputs = 1;
	dinfo->output[i].type = INTELFB_OUTPUT_ANALOG;

	/* setup the DDC bus for analog output */
	intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA, "CRTDDC_A");
	i++;

    /* need to add the output busses for each device
       - this function is very incomplete
       - i915GM has LVDS and TVOUT for example
    */
    switch(dinfo->chipset) {
	case INTEL_830M:
	case INTEL_845G:
	case INTEL_855GM:
	case INTEL_865G:
		dinfo->output[i].type = INTELFB_OUTPUT_DVO;
		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOD, "DVODDC_D");
		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "DVOI2C_E");
		i++;
		break;
	case INTEL_915G:
	case INTEL_915GM:
		/* has  some LVDS + tv-out */
	case INTEL_945G:
	case INTEL_945GM:
		/* SDVO ports have a single control bus - 2 devices */
		dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
		intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus, GPIOE, "SDVOCTRL_E");
		/* TODO: initialize the SDVO */
//		I830SDVOInit(pScrn, i, DVOB);
		i++;

		/* set up SDVOC */
		dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
		dinfo->output[i].i2c_bus = dinfo->output[i - 1].i2c_bus;
		/* TODO: initialize the SDVO */
//		I830SDVOInit(pScrn, i, DVOC);
		i++;
		break;
	}
	dinfo->num_outputs = i;
}

void intelfb_delete_i2c_busses(struct intelfb_info *dinfo)
{
	int i;

	for (i = 0; i < MAX_OUTPUTS; i++) {
		if (dinfo->output[i].i2c_bus.dinfo) {
			i2c_bit_del_bus(&dinfo->output[i].i2c_bus.adapter);
			dinfo->output[i].i2c_bus.dinfo = NULL;
		}
		if (dinfo->output[i].ddc_bus.dinfo) {
			i2c_bit_del_bus(&dinfo->output[i].ddc_bus.adapter);
			dinfo->output[i].ddc_bus.dinfo = NULL;
		}
	}
}
Loading