drm/i915: Improve CRTDDC mapping by using VBT info
Use VBT information to determine which DDC bus to use for CRTDCC. Fall back to GPIOA if VBT info is not available. Signed-off-by: David Müller <d.mueller@elsoft.ch> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Tested on: 855 (David), and 945GM, 965GM, GM45, and G45 (anholt)
This commit is contained in:
committed by
Eric Anholt
parent
a09ba7faf7
commit
db54501900
@@ -222,6 +222,7 @@ typedef struct drm_i915_private {
|
|||||||
unsigned int edp_support:1;
|
unsigned int edp_support:1;
|
||||||
int lvds_ssc_freq;
|
int lvds_ssc_freq;
|
||||||
|
|
||||||
|
int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
|
||||||
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
|
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
|
||||||
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
|
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
|
||||||
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
|
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
|
||||||
|
@@ -59,6 +59,16 @@ find_section(struct bdb_header *bdb, int section_id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u16
|
||||||
|
get_blocksize(void *p)
|
||||||
|
{
|
||||||
|
u16 *block_ptr, block_size;
|
||||||
|
|
||||||
|
block_ptr = (u16 *)((char *)p - 2);
|
||||||
|
block_size = *block_ptr;
|
||||||
|
return block_size;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
|
||||||
struct lvds_dvo_timing *dvo_timing)
|
struct lvds_dvo_timing *dvo_timing)
|
||||||
@@ -214,6 +224,41 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_general_definitions(struct drm_i915_private *dev_priv,
|
||||||
|
struct bdb_header *bdb)
|
||||||
|
{
|
||||||
|
struct bdb_general_definitions *general;
|
||||||
|
const int crt_bus_map_table[] = {
|
||||||
|
GPIOB,
|
||||||
|
GPIOA,
|
||||||
|
GPIOC,
|
||||||
|
GPIOD,
|
||||||
|
GPIOE,
|
||||||
|
GPIOF,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set sensible defaults in case we can't find the general block
|
||||||
|
or it is the wrong chipset */
|
||||||
|
dev_priv->crt_ddc_bus = -1;
|
||||||
|
|
||||||
|
general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||||
|
if (general) {
|
||||||
|
u16 block_size = get_blocksize(general);
|
||||||
|
if (block_size >= sizeof(*general)) {
|
||||||
|
int bus_pin = general->crt_ddc_gmbus_pin;
|
||||||
|
DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
|
||||||
|
if ((bus_pin >= 1) && (bus_pin <= 6)) {
|
||||||
|
dev_priv->crt_ddc_bus =
|
||||||
|
crt_bus_map_table[bus_pin-1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
|
||||||
|
block_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
||||||
struct bdb_header *bdb)
|
struct bdb_header *bdb)
|
||||||
@@ -222,7 +267,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
|||||||
struct bdb_general_definitions *p_defs;
|
struct bdb_general_definitions *p_defs;
|
||||||
struct child_device_config *p_child;
|
struct child_device_config *p_child;
|
||||||
int i, child_device_num, count;
|
int i, child_device_num, count;
|
||||||
u16 block_size, *block_ptr;
|
u16 block_size;
|
||||||
|
|
||||||
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
|
||||||
if (!p_defs) {
|
if (!p_defs) {
|
||||||
@@ -240,8 +285,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* get the block size of general definitions */
|
/* get the block size of general definitions */
|
||||||
block_ptr = (u16 *)((char *)p_defs - 2);
|
block_size = get_blocksize(p_defs);
|
||||||
block_size = *block_ptr;
|
|
||||||
/* get the number of child device */
|
/* get the number of child device */
|
||||||
child_device_num = (block_size - sizeof(*p_defs)) /
|
child_device_num = (block_size - sizeof(*p_defs)) /
|
||||||
sizeof(*p_child);
|
sizeof(*p_child);
|
||||||
@@ -362,6 +406,7 @@ intel_init_bios(struct drm_device *dev)
|
|||||||
|
|
||||||
/* Grab useful general definitions */
|
/* Grab useful general definitions */
|
||||||
parse_general_features(dev_priv, bdb);
|
parse_general_features(dev_priv, bdb);
|
||||||
|
parse_general_definitions(dev_priv, bdb);
|
||||||
parse_lfp_panel_data(dev_priv, bdb);
|
parse_lfp_panel_data(dev_priv, bdb);
|
||||||
parse_sdvo_panel_data(dev_priv, bdb);
|
parse_sdvo_panel_data(dev_priv, bdb);
|
||||||
parse_sdvo_device_mapping(dev_priv, bdb);
|
parse_sdvo_device_mapping(dev_priv, bdb);
|
||||||
|
@@ -508,6 +508,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
struct intel_output *intel_output;
|
struct intel_output *intel_output;
|
||||||
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
u32 i2c_reg;
|
u32 i2c_reg;
|
||||||
|
|
||||||
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||||
@@ -527,8 +528,12 @@ void intel_crt_init(struct drm_device *dev)
|
|||||||
/* Set up the DDC bus. */
|
/* Set up the DDC bus. */
|
||||||
if (IS_IGDNG(dev))
|
if (IS_IGDNG(dev))
|
||||||
i2c_reg = PCH_GPIOA;
|
i2c_reg = PCH_GPIOA;
|
||||||
else
|
else {
|
||||||
i2c_reg = GPIOA;
|
i2c_reg = GPIOA;
|
||||||
|
/* Use VBT information for CRT DDC if available */
|
||||||
|
if (dev_priv->crt_ddc_bus != -1)
|
||||||
|
i2c_reg = dev_priv->crt_ddc_bus;
|
||||||
|
}
|
||||||
intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
|
intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
|
||||||
if (!intel_output->ddc_bus) {
|
if (!intel_output->ddc_bus) {
|
||||||
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||||
|
Reference in New Issue
Block a user