forked from KolibriOS/kolibrios
init modesetting
git-svn-id: svn://kolibrios.org@2330 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
bb704ae063
commit
2d34afd1e0
144
drivers/video/drm/i915/dvo.h
Normal file
144
drivers/video/drm/i915/dvo.h
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright © 2006 Eric Anholt
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_DVO_H
|
||||
#define _INTEL_DVO_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
struct intel_dvo_device {
|
||||
const char *name;
|
||||
int type;
|
||||
/* DVOA/B/C output register */
|
||||
u32 dvo_reg;
|
||||
/* GPIO register used for i2c bus to control this device */
|
||||
u32 gpio;
|
||||
int slave_addr;
|
||||
|
||||
const struct intel_dvo_dev_ops *dev_ops;
|
||||
void *dev_priv;
|
||||
struct i2c_adapter *i2c_bus;
|
||||
};
|
||||
|
||||
struct intel_dvo_dev_ops {
|
||||
/*
|
||||
* Initialize the device at startup time.
|
||||
* Returns NULL if the device does not exist.
|
||||
*/
|
||||
bool (*init)(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *i2cbus);
|
||||
|
||||
/*
|
||||
* Called to allow the output a chance to create properties after the
|
||||
* RandR objects have been created.
|
||||
*/
|
||||
void (*create_resources)(struct intel_dvo_device *dvo);
|
||||
|
||||
/*
|
||||
* Turn on/off output or set intermediate power levels if available.
|
||||
*
|
||||
* Unsupported intermediate modes drop to the lower power setting.
|
||||
* If the mode is DPMSModeOff, the output must be disabled,
|
||||
* as the DPLL may be disabled afterwards.
|
||||
*/
|
||||
void (*dpms)(struct intel_dvo_device *dvo, int mode);
|
||||
|
||||
/*
|
||||
* Callback for testing a video mode for a given output.
|
||||
*
|
||||
* This function should only check for cases where a mode can't
|
||||
* be supported on the output specifically, and not represent
|
||||
* generic CRTC limitations.
|
||||
*
|
||||
* \return MODE_OK if the mode is valid, or another MODE_* otherwise.
|
||||
*/
|
||||
int (*mode_valid)(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
/*
|
||||
* Callback to adjust the mode to be set in the CRTC.
|
||||
*
|
||||
* This allows an output to adjust the clock or even the entire set of
|
||||
* timings, which is used for panels with fixed timings or for
|
||||
* buses with clock limitations.
|
||||
*/
|
||||
bool (*mode_fixup)(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
|
||||
/*
|
||||
* Callback for preparing mode changes on an output
|
||||
*/
|
||||
void (*prepare)(struct intel_dvo_device *dvo);
|
||||
|
||||
/*
|
||||
* Callback for committing mode changes on an output
|
||||
*/
|
||||
void (*commit)(struct intel_dvo_device *dvo);
|
||||
|
||||
/*
|
||||
* Callback for setting up a video mode after fixups have been made.
|
||||
*
|
||||
* This is only called while the output is disabled. The dpms callback
|
||||
* must be all that's necessary for the output, to turn the output on
|
||||
* after this function is called.
|
||||
*/
|
||||
void (*mode_set)(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
|
||||
/*
|
||||
* Probe for a connected output, and return detect_status.
|
||||
*/
|
||||
enum drm_connector_status (*detect)(struct intel_dvo_device *dvo);
|
||||
|
||||
/**
|
||||
* Query the device for the modes it provides.
|
||||
*
|
||||
* This function may also update MonInfo, mm_width, and mm_height.
|
||||
*
|
||||
* \return singly-linked list of modes or NULL if no modes found.
|
||||
*/
|
||||
struct drm_display_mode *(*get_modes)(struct intel_dvo_device *dvo);
|
||||
|
||||
/**
|
||||
* Clean up driver-specific bits of the output
|
||||
*/
|
||||
void (*destroy) (struct intel_dvo_device *dvo);
|
||||
|
||||
/**
|
||||
* Debugging hook to dump device registers to log file
|
||||
*/
|
||||
void (*dump_regs)(struct intel_dvo_device *dvo);
|
||||
};
|
||||
|
||||
extern struct intel_dvo_dev_ops sil164_ops;
|
||||
extern struct intel_dvo_dev_ops ch7xxx_ops;
|
||||
extern struct intel_dvo_dev_ops ivch_ops;
|
||||
extern struct intel_dvo_dev_ops tfp410_ops;
|
||||
extern struct intel_dvo_dev_ops ch7017_ops;
|
||||
|
||||
#endif /* _INTEL_DVO_H */
|
401
drivers/video/drm/i915/dvo_ch7017.c
Normal file
401
drivers/video/drm/i915/dvo_ch7017.c
Normal file
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
|
||||
#define CH7017_TV_DISPLAY_MODE 0x00
|
||||
#define CH7017_FLICKER_FILTER 0x01
|
||||
#define CH7017_VIDEO_BANDWIDTH 0x02
|
||||
#define CH7017_TEXT_ENHANCEMENT 0x03
|
||||
#define CH7017_START_ACTIVE_VIDEO 0x04
|
||||
#define CH7017_HORIZONTAL_POSITION 0x05
|
||||
#define CH7017_VERTICAL_POSITION 0x06
|
||||
#define CH7017_BLACK_LEVEL 0x07
|
||||
#define CH7017_CONTRAST_ENHANCEMENT 0x08
|
||||
#define CH7017_TV_PLL 0x09
|
||||
#define CH7017_TV_PLL_M 0x0a
|
||||
#define CH7017_TV_PLL_N 0x0b
|
||||
#define CH7017_SUB_CARRIER_0 0x0c
|
||||
#define CH7017_CIV_CONTROL 0x10
|
||||
#define CH7017_CIV_0 0x11
|
||||
#define CH7017_CHROMA_BOOST 0x14
|
||||
#define CH7017_CLOCK_MODE 0x1c
|
||||
#define CH7017_INPUT_CLOCK 0x1d
|
||||
#define CH7017_GPIO_CONTROL 0x1e
|
||||
#define CH7017_INPUT_DATA_FORMAT 0x1f
|
||||
#define CH7017_CONNECTION_DETECT 0x20
|
||||
#define CH7017_DAC_CONTROL 0x21
|
||||
#define CH7017_BUFFERED_CLOCK_OUTPUT 0x22
|
||||
#define CH7017_DEFEAT_VSYNC 0x47
|
||||
#define CH7017_TEST_PATTERN 0x48
|
||||
|
||||
#define CH7017_POWER_MANAGEMENT 0x49
|
||||
/** Enables the TV output path. */
|
||||
#define CH7017_TV_EN (1 << 0)
|
||||
#define CH7017_DAC0_POWER_DOWN (1 << 1)
|
||||
#define CH7017_DAC1_POWER_DOWN (1 << 2)
|
||||
#define CH7017_DAC2_POWER_DOWN (1 << 3)
|
||||
#define CH7017_DAC3_POWER_DOWN (1 << 4)
|
||||
/** Powers down the TV out block, and DAC0-3 */
|
||||
#define CH7017_TV_POWER_DOWN_EN (1 << 5)
|
||||
|
||||
#define CH7017_VERSION_ID 0x4a
|
||||
|
||||
#define CH7017_DEVICE_ID 0x4b
|
||||
#define CH7017_DEVICE_ID_VALUE 0x1b
|
||||
#define CH7018_DEVICE_ID_VALUE 0x1a
|
||||
#define CH7019_DEVICE_ID_VALUE 0x19
|
||||
|
||||
#define CH7017_XCLK_D2_ADJUST 0x53
|
||||
#define CH7017_UP_SCALER_COEFF_0 0x55
|
||||
#define CH7017_UP_SCALER_COEFF_1 0x56
|
||||
#define CH7017_UP_SCALER_COEFF_2 0x57
|
||||
#define CH7017_UP_SCALER_COEFF_3 0x58
|
||||
#define CH7017_UP_SCALER_COEFF_4 0x59
|
||||
#define CH7017_UP_SCALER_VERTICAL_INC_0 0x5a
|
||||
#define CH7017_UP_SCALER_VERTICAL_INC_1 0x5b
|
||||
#define CH7017_GPIO_INVERT 0x5c
|
||||
#define CH7017_UP_SCALER_HORIZONTAL_INC_0 0x5d
|
||||
#define CH7017_UP_SCALER_HORIZONTAL_INC_1 0x5e
|
||||
|
||||
#define CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT 0x5f
|
||||
/**< Low bits of horizontal active pixel input */
|
||||
|
||||
#define CH7017_ACTIVE_INPUT_LINE_OUTPUT 0x60
|
||||
/** High bits of horizontal active pixel input */
|
||||
#define CH7017_LVDS_HAP_INPUT_MASK (0x7 << 0)
|
||||
/** High bits of vertical active line output */
|
||||
#define CH7017_LVDS_VAL_HIGH_MASK (0x7 << 3)
|
||||
|
||||
#define CH7017_VERTICAL_ACTIVE_LINE_OUTPUT 0x61
|
||||
/**< Low bits of vertical active line output */
|
||||
|
||||
#define CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT 0x62
|
||||
/**< Low bits of horizontal active pixel output */
|
||||
|
||||
#define CH7017_LVDS_POWER_DOWN 0x63
|
||||
/** High bits of horizontal active pixel output */
|
||||
#define CH7017_LVDS_HAP_HIGH_MASK (0x7 << 0)
|
||||
/** Enables the LVDS power down state transition */
|
||||
#define CH7017_LVDS_POWER_DOWN_EN (1 << 6)
|
||||
/** Enables the LVDS upscaler */
|
||||
#define CH7017_LVDS_UPSCALER_EN (1 << 7)
|
||||
#define CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED 0x08
|
||||
|
||||
#define CH7017_LVDS_ENCODING 0x64
|
||||
#define CH7017_LVDS_DITHER_2D (1 << 2)
|
||||
#define CH7017_LVDS_DITHER_DIS (1 << 3)
|
||||
#define CH7017_LVDS_DUAL_CHANNEL_EN (1 << 4)
|
||||
#define CH7017_LVDS_24_BIT (1 << 5)
|
||||
|
||||
#define CH7017_LVDS_ENCODING_2 0x65
|
||||
|
||||
#define CH7017_LVDS_PLL_CONTROL 0x66
|
||||
/** Enables the LVDS panel output path */
|
||||
#define CH7017_LVDS_PANEN (1 << 0)
|
||||
/** Enables the LVDS panel backlight */
|
||||
#define CH7017_LVDS_BKLEN (1 << 3)
|
||||
|
||||
#define CH7017_POWER_SEQUENCING_T1 0x67
|
||||
#define CH7017_POWER_SEQUENCING_T2 0x68
|
||||
#define CH7017_POWER_SEQUENCING_T3 0x69
|
||||
#define CH7017_POWER_SEQUENCING_T4 0x6a
|
||||
#define CH7017_POWER_SEQUENCING_T5 0x6b
|
||||
#define CH7017_GPIO_DRIVER_TYPE 0x6c
|
||||
#define CH7017_GPIO_DATA 0x6d
|
||||
#define CH7017_GPIO_DIRECTION_CONTROL 0x6e
|
||||
|
||||
#define CH7017_LVDS_PLL_FEEDBACK_DIV 0x71
|
||||
# define CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT 4
|
||||
# define CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT 0
|
||||
# define CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED 0x80
|
||||
|
||||
#define CH7017_LVDS_PLL_VCO_CONTROL 0x72
|
||||
# define CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED 0x80
|
||||
# define CH7017_LVDS_PLL_VCO_SHIFT 4
|
||||
# define CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT 0
|
||||
|
||||
#define CH7017_OUTPUTS_ENABLE 0x73
|
||||
# define CH7017_CHARGE_PUMP_LOW 0x0
|
||||
# define CH7017_CHARGE_PUMP_HIGH 0x3
|
||||
# define CH7017_LVDS_CHANNEL_A (1 << 3)
|
||||
# define CH7017_LVDS_CHANNEL_B (1 << 4)
|
||||
# define CH7017_TV_DAC_A (1 << 5)
|
||||
# define CH7017_TV_DAC_B (1 << 6)
|
||||
# define CH7017_DDC_SELECT_DC2 (1 << 7)
|
||||
|
||||
#define CH7017_LVDS_OUTPUT_AMPLITUDE 0x74
|
||||
#define CH7017_LVDS_PLL_EMI_REDUCTION 0x75
|
||||
#define CH7017_LVDS_POWER_DOWN_FLICKER 0x76
|
||||
|
||||
#define CH7017_LVDS_CONTROL_2 0x78
|
||||
# define CH7017_LOOP_FILTER_SHIFT 5
|
||||
# define CH7017_PHASE_DETECTOR_SHIFT 0
|
||||
|
||||
#define CH7017_BANG_LIMIT_CONTROL 0x7f
|
||||
|
||||
struct ch7017_priv {
|
||||
uint8_t dummy;
|
||||
};
|
||||
|
||||
static void ch7017_dump_regs(struct intel_dvo_device *dvo);
|
||||
static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
|
||||
|
||||
static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val)
|
||||
{
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = &addr,
|
||||
},
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = val,
|
||||
}
|
||||
};
|
||||
return i2c_transfer(dvo->i2c_bus, msgs, 2) == 2;
|
||||
}
|
||||
|
||||
static bool ch7017_write(struct intel_dvo_device *dvo, u8 addr, u8 val)
|
||||
{
|
||||
uint8_t buf[2] = { addr, val };
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = buf,
|
||||
};
|
||||
return i2c_transfer(dvo->i2c_bus, &msg, 1) == 1;
|
||||
}
|
||||
|
||||
/** Probes for a CH7017 on the given bus and slave address. */
|
||||
static bool ch7017_init(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
struct ch7017_priv *priv;
|
||||
const char *str;
|
||||
u8 val;
|
||||
|
||||
priv = kzalloc(sizeof(struct ch7017_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return false;
|
||||
|
||||
dvo->i2c_bus = adapter;
|
||||
dvo->dev_priv = priv;
|
||||
|
||||
if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
|
||||
goto fail;
|
||||
|
||||
switch (val) {
|
||||
case CH7017_DEVICE_ID_VALUE:
|
||||
str = "ch7017";
|
||||
break;
|
||||
case CH7018_DEVICE_ID_VALUE:
|
||||
str = "ch7018";
|
||||
break;
|
||||
case CH7019_DEVICE_ID_VALUE:
|
||||
str = "ch7019";
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("ch701x not detected, got %d: from %s "
|
||||
"slave %d.\n",
|
||||
val, adapter->name,dvo->slave_addr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s detected on %s, addr %d\n",
|
||||
str, adapter->name, dvo->slave_addr);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
kfree(priv);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
|
||||
{
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 160000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void ch7017_mode_set(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
uint8_t lvds_pll_feedback_div, lvds_pll_vco_control;
|
||||
uint8_t outputs_enable, lvds_control_2, lvds_power_down;
|
||||
uint8_t horizontal_active_pixel_input;
|
||||
uint8_t horizontal_active_pixel_output, vertical_active_line_output;
|
||||
uint8_t active_input_line_output;
|
||||
|
||||
DRM_DEBUG_KMS("Registers before mode setting\n");
|
||||
ch7017_dump_regs(dvo);
|
||||
|
||||
/* LVDS PLL settings from page 75 of 7017-7017ds.pdf*/
|
||||
if (mode->clock < 100000) {
|
||||
outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_LOW;
|
||||
lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
|
||||
(2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
|
||||
(13 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
|
||||
lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
|
||||
(2 << CH7017_LVDS_PLL_VCO_SHIFT) |
|
||||
(3 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
|
||||
lvds_control_2 = (1 << CH7017_LOOP_FILTER_SHIFT) |
|
||||
(0 << CH7017_PHASE_DETECTOR_SHIFT);
|
||||
} else {
|
||||
outputs_enable = CH7017_LVDS_CHANNEL_A | CH7017_CHARGE_PUMP_HIGH;
|
||||
lvds_pll_feedback_div = CH7017_LVDS_PLL_FEEDBACK_DEFAULT_RESERVED |
|
||||
(2 << CH7017_LVDS_PLL_FEED_BACK_DIVIDER_SHIFT) |
|
||||
(3 << CH7017_LVDS_PLL_FEED_FORWARD_DIVIDER_SHIFT);
|
||||
lvds_pll_feedback_div = 35;
|
||||
lvds_control_2 = (3 << CH7017_LOOP_FILTER_SHIFT) |
|
||||
(0 << CH7017_PHASE_DETECTOR_SHIFT);
|
||||
if (1) { /* XXX: dual channel panel detection. Assume yes for now. */
|
||||
outputs_enable |= CH7017_LVDS_CHANNEL_B;
|
||||
lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
|
||||
(2 << CH7017_LVDS_PLL_VCO_SHIFT) |
|
||||
(13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
|
||||
} else {
|
||||
lvds_pll_vco_control = CH7017_LVDS_PLL_VCO_DEFAULT_RESERVED |
|
||||
(1 << CH7017_LVDS_PLL_VCO_SHIFT) |
|
||||
(13 << CH7017_LVDS_PLL_POST_SCALE_DIV_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
horizontal_active_pixel_input = mode->hdisplay & 0x00ff;
|
||||
|
||||
vertical_active_line_output = mode->vdisplay & 0x00ff;
|
||||
horizontal_active_pixel_output = mode->hdisplay & 0x00ff;
|
||||
|
||||
active_input_line_output = ((mode->hdisplay & 0x0700) >> 8) |
|
||||
(((mode->vdisplay & 0x0700) >> 8) << 3);
|
||||
|
||||
lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
|
||||
(mode->hdisplay & 0x0700) >> 8;
|
||||
|
||||
ch7017_dpms(dvo, DRM_MODE_DPMS_OFF);
|
||||
ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
|
||||
horizontal_active_pixel_input);
|
||||
ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
|
||||
horizontal_active_pixel_output);
|
||||
ch7017_write(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT,
|
||||
vertical_active_line_output);
|
||||
ch7017_write(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT,
|
||||
active_input_line_output);
|
||||
ch7017_write(dvo, CH7017_LVDS_PLL_VCO_CONTROL, lvds_pll_vco_control);
|
||||
ch7017_write(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, lvds_pll_feedback_div);
|
||||
ch7017_write(dvo, CH7017_LVDS_CONTROL_2, lvds_control_2);
|
||||
ch7017_write(dvo, CH7017_OUTPUTS_ENABLE, outputs_enable);
|
||||
|
||||
/* Turn the LVDS back on with new settings. */
|
||||
ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, lvds_power_down);
|
||||
|
||||
DRM_DEBUG_KMS("Registers after mode setting\n");
|
||||
ch7017_dump_regs(dvo);
|
||||
}
|
||||
|
||||
/* set the CH7017 power state */
|
||||
static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);
|
||||
|
||||
/* Turn off TV/VGA, and never turn it on since we don't support it. */
|
||||
ch7017_write(dvo, CH7017_POWER_MANAGEMENT,
|
||||
CH7017_DAC0_POWER_DOWN |
|
||||
CH7017_DAC1_POWER_DOWN |
|
||||
CH7017_DAC2_POWER_DOWN |
|
||||
CH7017_DAC3_POWER_DOWN |
|
||||
CH7017_TV_POWER_DOWN_EN);
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON) {
|
||||
/* Turn on the LVDS */
|
||||
ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
|
||||
val & ~CH7017_LVDS_POWER_DOWN_EN);
|
||||
} else {
|
||||
/* Turn off the LVDS */
|
||||
ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
|
||||
val | CH7017_LVDS_POWER_DOWN_EN);
|
||||
}
|
||||
|
||||
/* XXX: Should actually wait for update power status somehow */
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
static void ch7017_dump_regs(struct intel_dvo_device *dvo)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
#define DUMP(reg) \
|
||||
do { \
|
||||
ch7017_read(dvo, reg, &val); \
|
||||
DRM_DEBUG_KMS(#reg ": %02x\n", val); \
|
||||
} while (0)
|
||||
|
||||
DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT);
|
||||
DUMP(CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT);
|
||||
DUMP(CH7017_VERTICAL_ACTIVE_LINE_OUTPUT);
|
||||
DUMP(CH7017_ACTIVE_INPUT_LINE_OUTPUT);
|
||||
DUMP(CH7017_LVDS_PLL_VCO_CONTROL);
|
||||
DUMP(CH7017_LVDS_PLL_FEEDBACK_DIV);
|
||||
DUMP(CH7017_LVDS_CONTROL_2);
|
||||
DUMP(CH7017_OUTPUTS_ENABLE);
|
||||
DUMP(CH7017_LVDS_POWER_DOWN);
|
||||
}
|
||||
|
||||
static void ch7017_destroy(struct intel_dvo_device *dvo)
|
||||
{
|
||||
struct ch7017_priv *priv = dvo->dev_priv;
|
||||
|
||||
if (priv) {
|
||||
kfree(priv);
|
||||
dvo->dev_priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ch7017_ops = {
|
||||
.init = ch7017_init,
|
||||
.detect = ch7017_detect,
|
||||
.mode_valid = ch7017_mode_valid,
|
||||
.mode_set = ch7017_mode_set,
|
||||
.dpms = ch7017_dpms,
|
||||
.dump_regs = ch7017_dump_regs,
|
||||
.destroy = ch7017_destroy,
|
||||
};
|
331
drivers/video/drm/i915/dvo_ch7xxx.c
Normal file
331
drivers/video/drm/i915/dvo_ch7xxx.c
Normal file
@ -0,0 +1,331 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright © 2006 Dave Airlie
|
||||
|
||||
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 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 AUTHOR 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 "dvo.h"
|
||||
|
||||
#define CH7xxx_REG_VID 0x4a
|
||||
#define CH7xxx_REG_DID 0x4b
|
||||
|
||||
#define CH7011_VID 0x83 /* 7010 as well */
|
||||
#define CH7009A_VID 0x84
|
||||
#define CH7009B_VID 0x85
|
||||
#define CH7301_VID 0x95
|
||||
|
||||
#define CH7xxx_VID 0x84
|
||||
#define CH7xxx_DID 0x17
|
||||
|
||||
#define CH7xxx_NUM_REGS 0x4c
|
||||
|
||||
#define CH7xxx_CM 0x1c
|
||||
#define CH7xxx_CM_XCM (1<<0)
|
||||
#define CH7xxx_CM_MCP (1<<2)
|
||||
#define CH7xxx_INPUT_CLOCK 0x1d
|
||||
#define CH7xxx_GPIO 0x1e
|
||||
#define CH7xxx_GPIO_HPIR (1<<3)
|
||||
#define CH7xxx_IDF 0x1f
|
||||
|
||||
#define CH7xxx_IDF_HSP (1<<3)
|
||||
#define CH7xxx_IDF_VSP (1<<4)
|
||||
|
||||
#define CH7xxx_CONNECTION_DETECT 0x20
|
||||
#define CH7xxx_CDET_DVI (1<<5)
|
||||
|
||||
#define CH7301_DAC_CNTL 0x21
|
||||
#define CH7301_HOTPLUG 0x23
|
||||
#define CH7xxx_TCTL 0x31
|
||||
#define CH7xxx_TVCO 0x32
|
||||
#define CH7xxx_TPCP 0x33
|
||||
#define CH7xxx_TPD 0x34
|
||||
#define CH7xxx_TPVT 0x35
|
||||
#define CH7xxx_TLPF 0x36
|
||||
#define CH7xxx_TCT 0x37
|
||||
#define CH7301_TEST_PATTERN 0x48
|
||||
|
||||
#define CH7xxx_PM 0x49
|
||||
#define CH7xxx_PM_FPD (1<<0)
|
||||
#define CH7301_PM_DACPD0 (1<<1)
|
||||
#define CH7301_PM_DACPD1 (1<<2)
|
||||
#define CH7301_PM_DACPD2 (1<<3)
|
||||
#define CH7xxx_PM_DVIL (1<<6)
|
||||
#define CH7xxx_PM_DVIP (1<<7)
|
||||
|
||||
#define CH7301_SYNC_POLARITY 0x56
|
||||
#define CH7301_SYNC_RGB_YUV (1<<0)
|
||||
#define CH7301_SYNC_POL_DVI (1<<5)
|
||||
|
||||
/** @file
|
||||
* driver for the Chrontel 7xxx DVI chip over DVO.
|
||||
*/
|
||||
|
||||
static struct ch7xxx_id_struct {
|
||||
uint8_t vid;
|
||||
char *name;
|
||||
} ch7xxx_ids[] = {
|
||||
{ CH7011_VID, "CH7011" },
|
||||
{ CH7009A_VID, "CH7009A" },
|
||||
{ CH7009B_VID, "CH7009B" },
|
||||
{ CH7301_VID, "CH7301" },
|
||||
};
|
||||
|
||||
struct ch7xxx_priv {
|
||||
bool quiet;
|
||||
};
|
||||
|
||||
static char *ch7xxx_get_id(uint8_t vid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ch7xxx_ids); i++) {
|
||||
if (ch7xxx_ids[i].vid == vid)
|
||||
return ch7xxx_ids[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Reads an 8 bit register */
|
||||
static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
||||
{
|
||||
struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = in_buf,
|
||||
}
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2) {
|
||||
*ch = in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!ch7xxx->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Writes an 8 bit register */
|
||||
static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
||||
{
|
||||
struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = out_buf,
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = ch;
|
||||
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!ch7xxx->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ch7xxx_init(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
/* this will detect the CH7xxx chip on the specified i2c bus */
|
||||
struct ch7xxx_priv *ch7xxx;
|
||||
uint8_t vendor, device;
|
||||
char *name;
|
||||
|
||||
ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL);
|
||||
if (ch7xxx == NULL)
|
||||
return false;
|
||||
|
||||
dvo->i2c_bus = adapter;
|
||||
dvo->dev_priv = ch7xxx;
|
||||
ch7xxx->quiet = true;
|
||||
|
||||
if (!ch7xxx_readb(dvo, CH7xxx_REG_VID, &vendor))
|
||||
goto out;
|
||||
|
||||
name = ch7xxx_get_id(vendor);
|
||||
if (!name) {
|
||||
DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
|
||||
"slave %d.\n",
|
||||
vendor, adapter->name, dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device))
|
||||
goto out;
|
||||
|
||||
if (device != CH7xxx_DID) {
|
||||
DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
|
||||
"slave %d.\n",
|
||||
vendor, adapter->name, dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ch7xxx->quiet = false;
|
||||
DRM_DEBUG_KMS("Detected %s chipset, vendor/device ID 0x%02x/0x%02x\n",
|
||||
name, vendor, device);
|
||||
return true;
|
||||
out:
|
||||
kfree(ch7xxx);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status ch7xxx_detect(struct intel_dvo_device *dvo)
|
||||
{
|
||||
uint8_t cdet, orig_pm, pm;
|
||||
|
||||
ch7xxx_readb(dvo, CH7xxx_PM, &orig_pm);
|
||||
|
||||
pm = orig_pm;
|
||||
pm &= ~CH7xxx_PM_FPD;
|
||||
pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
|
||||
|
||||
ch7xxx_writeb(dvo, CH7xxx_PM, pm);
|
||||
|
||||
ch7xxx_readb(dvo, CH7xxx_CONNECTION_DETECT, &cdet);
|
||||
|
||||
ch7xxx_writeb(dvo, CH7xxx_PM, orig_pm);
|
||||
|
||||
if (cdet & CH7xxx_CDET_DVI)
|
||||
return connector_status_connected;
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_mode_status ch7xxx_mode_valid(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 165000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
uint8_t tvco, tpcp, tpd, tlpf, idf;
|
||||
|
||||
if (mode->clock <= 65000) {
|
||||
tvco = 0x23;
|
||||
tpcp = 0x08;
|
||||
tpd = 0x16;
|
||||
tlpf = 0x60;
|
||||
} else {
|
||||
tvco = 0x2d;
|
||||
tpcp = 0x06;
|
||||
tpd = 0x26;
|
||||
tlpf = 0xa0;
|
||||
}
|
||||
|
||||
ch7xxx_writeb(dvo, CH7xxx_TCTL, 0x00);
|
||||
ch7xxx_writeb(dvo, CH7xxx_TVCO, tvco);
|
||||
ch7xxx_writeb(dvo, CH7xxx_TPCP, tpcp);
|
||||
ch7xxx_writeb(dvo, CH7xxx_TPD, tpd);
|
||||
ch7xxx_writeb(dvo, CH7xxx_TPVT, 0x30);
|
||||
ch7xxx_writeb(dvo, CH7xxx_TLPF, tlpf);
|
||||
ch7xxx_writeb(dvo, CH7xxx_TCT, 0x00);
|
||||
|
||||
ch7xxx_readb(dvo, CH7xxx_IDF, &idf);
|
||||
|
||||
idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
idf |= CH7xxx_IDF_HSP;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
idf |= CH7xxx_IDF_HSP;
|
||||
|
||||
ch7xxx_writeb(dvo, CH7xxx_IDF, idf);
|
||||
}
|
||||
|
||||
/* set the CH7xxx power state */
|
||||
static void ch7xxx_dpms(struct intel_dvo_device *dvo, int mode)
|
||||
{
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
|
||||
else
|
||||
ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD);
|
||||
}
|
||||
|
||||
static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
|
||||
uint8_t val;
|
||||
if ((i % 8) == 0 )
|
||||
DRM_LOG_KMS("\n %02X: ", i);
|
||||
ch7xxx_readb(dvo, i, &val);
|
||||
DRM_LOG_KMS("%02X ", val);
|
||||
}
|
||||
}
|
||||
|
||||
static void ch7xxx_destroy(struct intel_dvo_device *dvo)
|
||||
{
|
||||
struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
|
||||
|
||||
if (ch7xxx) {
|
||||
kfree(ch7xxx);
|
||||
dvo->dev_priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ch7xxx_ops = {
|
||||
.init = ch7xxx_init,
|
||||
.detect = ch7xxx_detect,
|
||||
.mode_valid = ch7xxx_mode_valid,
|
||||
.mode_set = ch7xxx_mode_set,
|
||||
.dpms = ch7xxx_dpms,
|
||||
.dump_regs = ch7xxx_dump_regs,
|
||||
.destroy = ch7xxx_destroy,
|
||||
};
|
421
drivers/video/drm/i915/dvo_ivch.c
Normal file
421
drivers/video/drm/i915/dvo_ivch.c
Normal file
@ -0,0 +1,421 @@
|
||||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
|
||||
/*
|
||||
* register definitions for the i82807aa.
|
||||
*
|
||||
* Documentation on this chipset can be found in datasheet #29069001 at
|
||||
* intel.com.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VCH Revision & GMBus Base Addr
|
||||
*/
|
||||
#define VR00 0x00
|
||||
# define VR00_BASE_ADDRESS_MASK 0x007f
|
||||
|
||||
/*
|
||||
* Functionality Enable
|
||||
*/
|
||||
#define VR01 0x01
|
||||
|
||||
/*
|
||||
* Enable the panel fitter
|
||||
*/
|
||||
# define VR01_PANEL_FIT_ENABLE (1 << 3)
|
||||
/*
|
||||
* Enables the LCD display.
|
||||
*
|
||||
* This must not be set while VR01_DVO_BYPASS_ENABLE is set.
|
||||
*/
|
||||
# define VR01_LCD_ENABLE (1 << 2)
|
||||
/** Enables the DVO repeater. */
|
||||
# define VR01_DVO_BYPASS_ENABLE (1 << 1)
|
||||
/** Enables the DVO clock */
|
||||
# define VR01_DVO_ENABLE (1 << 0)
|
||||
|
||||
/*
|
||||
* LCD Interface Format
|
||||
*/
|
||||
#define VR10 0x10
|
||||
/** Enables LVDS output instead of CMOS */
|
||||
# define VR10_LVDS_ENABLE (1 << 4)
|
||||
/** Enables 18-bit LVDS output. */
|
||||
# define VR10_INTERFACE_1X18 (0 << 2)
|
||||
/** Enables 24-bit LVDS or CMOS output */
|
||||
# define VR10_INTERFACE_1X24 (1 << 2)
|
||||
/** Enables 2x18-bit LVDS or CMOS output. */
|
||||
# define VR10_INTERFACE_2X18 (2 << 2)
|
||||
/** Enables 2x24-bit LVDS output */
|
||||
# define VR10_INTERFACE_2X24 (3 << 2)
|
||||
|
||||
/*
|
||||
* VR20 LCD Horizontal Display Size
|
||||
*/
|
||||
#define VR20 0x20
|
||||
|
||||
/*
|
||||
* LCD Vertical Display Size
|
||||
*/
|
||||
#define VR21 0x20
|
||||
|
||||
/*
|
||||
* Panel power down status
|
||||
*/
|
||||
#define VR30 0x30
|
||||
/** Read only bit indicating that the panel is not in a safe poweroff state. */
|
||||
# define VR30_PANEL_ON (1 << 15)
|
||||
|
||||
#define VR40 0x40
|
||||
# define VR40_STALL_ENABLE (1 << 13)
|
||||
# define VR40_VERTICAL_INTERP_ENABLE (1 << 12)
|
||||
# define VR40_ENHANCED_PANEL_FITTING (1 << 11)
|
||||
# define VR40_HORIZONTAL_INTERP_ENABLE (1 << 10)
|
||||
# define VR40_AUTO_RATIO_ENABLE (1 << 9)
|
||||
# define VR40_CLOCK_GATING_ENABLE (1 << 8)
|
||||
|
||||
/*
|
||||
* Panel Fitting Vertical Ratio
|
||||
* (((image_height - 1) << 16) / ((panel_height - 1))) >> 2
|
||||
*/
|
||||
#define VR41 0x41
|
||||
|
||||
/*
|
||||
* Panel Fitting Horizontal Ratio
|
||||
* (((image_width - 1) << 16) / ((panel_width - 1))) >> 2
|
||||
*/
|
||||
#define VR42 0x42
|
||||
|
||||
/*
|
||||
* Horizontal Image Size
|
||||
*/
|
||||
#define VR43 0x43
|
||||
|
||||
/* VR80 GPIO 0
|
||||
*/
|
||||
#define VR80 0x80
|
||||
#define VR81 0x81
|
||||
#define VR82 0x82
|
||||
#define VR83 0x83
|
||||
#define VR84 0x84
|
||||
#define VR85 0x85
|
||||
#define VR86 0x86
|
||||
#define VR87 0x87
|
||||
|
||||
/* VR88 GPIO 8
|
||||
*/
|
||||
#define VR88 0x88
|
||||
|
||||
/* Graphics BIOS scratch 0
|
||||
*/
|
||||
#define VR8E 0x8E
|
||||
# define VR8E_PANEL_TYPE_MASK (0xf << 0)
|
||||
# define VR8E_PANEL_INTERFACE_CMOS (0 << 4)
|
||||
# define VR8E_PANEL_INTERFACE_LVDS (1 << 4)
|
||||
# define VR8E_FORCE_DEFAULT_PANEL (1 << 5)
|
||||
|
||||
/* Graphics BIOS scratch 1
|
||||
*/
|
||||
#define VR8F 0x8F
|
||||
# define VR8F_VCH_PRESENT (1 << 0)
|
||||
# define VR8F_DISPLAY_CONN (1 << 1)
|
||||
# define VR8F_POWER_MASK (0x3c)
|
||||
# define VR8F_POWER_POS (2)
|
||||
|
||||
|
||||
struct ivch_priv {
|
||||
bool quiet;
|
||||
|
||||
uint16_t width, height;
|
||||
};
|
||||
|
||||
|
||||
static void ivch_dump_regs(struct intel_dvo_device *dvo);
|
||||
|
||||
/**
|
||||
* Reads a register on the ivch.
|
||||
*
|
||||
* Each of the 256 registers are 16 bits long.
|
||||
*/
|
||||
static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
|
||||
{
|
||||
struct ivch_priv *priv = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
u8 out_buf[1];
|
||||
u8 in_buf[2];
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 0,
|
||||
},
|
||||
{
|
||||
.addr = 0,
|
||||
.flags = I2C_M_NOSTART,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD | I2C_M_NOSTART,
|
||||
.len = 2,
|
||||
.buf = in_buf,
|
||||
}
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 3) == 3) {
|
||||
*data = (in_buf[1] << 8) | in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!priv->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from "
|
||||
"%s:%02x.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Writes a 16-bit register on the ivch */
|
||||
static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
|
||||
{
|
||||
struct ivch_priv *priv = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
u8 out_buf[3];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 3,
|
||||
.buf = out_buf,
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = data & 0xff;
|
||||
out_buf[2] = data >> 8;
|
||||
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!priv->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Probes the given bus and slave address for an ivch */
|
||||
static bool ivch_init(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
struct ivch_priv *priv;
|
||||
uint16_t temp;
|
||||
|
||||
priv = kzalloc(sizeof(struct ivch_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return false;
|
||||
|
||||
dvo->i2c_bus = adapter;
|
||||
dvo->dev_priv = priv;
|
||||
priv->quiet = true;
|
||||
|
||||
if (!ivch_read(dvo, VR00, &temp))
|
||||
goto out;
|
||||
priv->quiet = false;
|
||||
|
||||
/* Since the identification bits are probably zeroes, which doesn't seem
|
||||
* very unique, check that the value in the base address field matches
|
||||
* the address it's responding on.
|
||||
*/
|
||||
if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->slave_addr) {
|
||||
DRM_DEBUG_KMS("ivch detect failed due to address mismatch "
|
||||
"(%d vs %d)\n",
|
||||
(temp & VR00_BASE_ADDRESS_MASK), dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ivch_read(dvo, VR20, &priv->width);
|
||||
ivch_read(dvo, VR21, &priv->height);
|
||||
|
||||
return true;
|
||||
|
||||
out:
|
||||
kfree(priv);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status ivch_detect(struct intel_dvo_device *dvo)
|
||||
{
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 112000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
/** Sets the power state of the panel connected to the ivch */
|
||||
static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
|
||||
{
|
||||
int i;
|
||||
uint16_t vr01, vr30, backlight;
|
||||
|
||||
/* Set the new power state of the panel. */
|
||||
if (!ivch_read(dvo, VR01, &vr01))
|
||||
return;
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
backlight = 1;
|
||||
else
|
||||
backlight = 0;
|
||||
ivch_write(dvo, VR80, backlight);
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
|
||||
else
|
||||
vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
|
||||
|
||||
ivch_write(dvo, VR01, vr01);
|
||||
|
||||
/* Wait for the panel to make its state transition */
|
||||
for (i = 0; i < 100; i++) {
|
||||
if (!ivch_read(dvo, VR30, &vr30))
|
||||
break;
|
||||
|
||||
if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DRM_MODE_DPMS_ON))
|
||||
break;
|
||||
udelay(1000);
|
||||
}
|
||||
/* wait some more; vch may fail to resync sometimes without this */
|
||||
udelay(16 * 1000);
|
||||
}
|
||||
|
||||
static void ivch_mode_set(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
uint16_t vr40 = 0;
|
||||
uint16_t vr01;
|
||||
|
||||
vr01 = 0;
|
||||
vr40 = (VR40_STALL_ENABLE | VR40_VERTICAL_INTERP_ENABLE |
|
||||
VR40_HORIZONTAL_INTERP_ENABLE);
|
||||
|
||||
if (mode->hdisplay != adjusted_mode->hdisplay ||
|
||||
mode->vdisplay != adjusted_mode->vdisplay) {
|
||||
uint16_t x_ratio, y_ratio;
|
||||
|
||||
vr01 |= VR01_PANEL_FIT_ENABLE;
|
||||
vr40 |= VR40_CLOCK_GATING_ENABLE;
|
||||
x_ratio = (((mode->hdisplay - 1) << 16) /
|
||||
(adjusted_mode->hdisplay - 1)) >> 2;
|
||||
y_ratio = (((mode->vdisplay - 1) << 16) /
|
||||
(adjusted_mode->vdisplay - 1)) >> 2;
|
||||
ivch_write (dvo, VR42, x_ratio);
|
||||
ivch_write (dvo, VR41, y_ratio);
|
||||
} else {
|
||||
vr01 &= ~VR01_PANEL_FIT_ENABLE;
|
||||
vr40 &= ~VR40_CLOCK_GATING_ENABLE;
|
||||
}
|
||||
vr40 &= ~VR40_AUTO_RATIO_ENABLE;
|
||||
|
||||
ivch_write(dvo, VR01, vr01);
|
||||
ivch_write(dvo, VR40, vr40);
|
||||
|
||||
ivch_dump_regs(dvo);
|
||||
}
|
||||
|
||||
static void ivch_dump_regs(struct intel_dvo_device *dvo)
|
||||
{
|
||||
uint16_t val;
|
||||
|
||||
ivch_read(dvo, VR00, &val);
|
||||
DRM_LOG_KMS("VR00: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR01, &val);
|
||||
DRM_LOG_KMS("VR01: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR30, &val);
|
||||
DRM_LOG_KMS("VR30: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR40, &val);
|
||||
DRM_LOG_KMS("VR40: 0x%04x\n", val);
|
||||
|
||||
/* GPIO registers */
|
||||
ivch_read(dvo, VR80, &val);
|
||||
DRM_LOG_KMS("VR80: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR81, &val);
|
||||
DRM_LOG_KMS("VR81: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR82, &val);
|
||||
DRM_LOG_KMS("VR82: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR83, &val);
|
||||
DRM_LOG_KMS("VR83: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR84, &val);
|
||||
DRM_LOG_KMS("VR84: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR85, &val);
|
||||
DRM_LOG_KMS("VR85: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR86, &val);
|
||||
DRM_LOG_KMS("VR86: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR87, &val);
|
||||
DRM_LOG_KMS("VR87: 0x%04x\n", val);
|
||||
ivch_read(dvo, VR88, &val);
|
||||
DRM_LOG_KMS("VR88: 0x%04x\n", val);
|
||||
|
||||
/* Scratch register 0 - AIM Panel type */
|
||||
ivch_read(dvo, VR8E, &val);
|
||||
DRM_LOG_KMS("VR8E: 0x%04x\n", val);
|
||||
|
||||
/* Scratch register 1 - Status register */
|
||||
ivch_read(dvo, VR8F, &val);
|
||||
DRM_LOG_KMS("VR8F: 0x%04x\n", val);
|
||||
}
|
||||
|
||||
static void ivch_destroy(struct intel_dvo_device *dvo)
|
||||
{
|
||||
struct ivch_priv *priv = dvo->dev_priv;
|
||||
|
||||
if (priv) {
|
||||
kfree(priv);
|
||||
dvo->dev_priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ivch_ops= {
|
||||
.init = ivch_init,
|
||||
.dpms = ivch_dpms,
|
||||
.mode_valid = ivch_mode_valid,
|
||||
.mode_set = ivch_mode_set,
|
||||
.detect = ivch_detect,
|
||||
.dump_regs = ivch_dump_regs,
|
||||
.destroy = ivch_destroy,
|
||||
};
|
263
drivers/video/drm/i915/dvo_sil164.c
Normal file
263
drivers/video/drm/i915/dvo_sil164.c
Normal file
@ -0,0 +1,263 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright © 2006 Dave Airlie
|
||||
|
||||
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 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 AUTHOR 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 "dvo.h"
|
||||
|
||||
#define SIL164_VID 0x0001
|
||||
#define SIL164_DID 0x0006
|
||||
|
||||
#define SIL164_VID_LO 0x00
|
||||
#define SIL164_VID_HI 0x01
|
||||
#define SIL164_DID_LO 0x02
|
||||
#define SIL164_DID_HI 0x03
|
||||
#define SIL164_REV 0x04
|
||||
#define SIL164_RSVD 0x05
|
||||
#define SIL164_FREQ_LO 0x06
|
||||
#define SIL164_FREQ_HI 0x07
|
||||
|
||||
#define SIL164_REG8 0x08
|
||||
#define SIL164_8_VEN (1<<5)
|
||||
#define SIL164_8_HEN (1<<4)
|
||||
#define SIL164_8_DSEL (1<<3)
|
||||
#define SIL164_8_BSEL (1<<2)
|
||||
#define SIL164_8_EDGE (1<<1)
|
||||
#define SIL164_8_PD (1<<0)
|
||||
|
||||
#define SIL164_REG9 0x09
|
||||
#define SIL164_9_VLOW (1<<7)
|
||||
#define SIL164_9_MSEL_MASK (0x7<<4)
|
||||
#define SIL164_9_TSEL (1<<3)
|
||||
#define SIL164_9_RSEN (1<<2)
|
||||
#define SIL164_9_HTPLG (1<<1)
|
||||
#define SIL164_9_MDI (1<<0)
|
||||
|
||||
#define SIL164_REGC 0x0c
|
||||
|
||||
struct sil164_priv {
|
||||
//I2CDevRec d;
|
||||
bool quiet;
|
||||
};
|
||||
|
||||
#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
|
||||
|
||||
static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
||||
{
|
||||
struct sil164_priv *sil = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = in_buf,
|
||||
}
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2) {
|
||||
*ch = in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!sil->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
||||
{
|
||||
struct sil164_priv *sil= dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = out_buf,
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = ch;
|
||||
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!sil->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Silicon Image 164 driver for chip on i2c bus */
|
||||
static bool sil164_init(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
/* this will detect the SIL164 chip on the specified i2c bus */
|
||||
struct sil164_priv *sil;
|
||||
unsigned char ch;
|
||||
|
||||
sil = kzalloc(sizeof(struct sil164_priv), GFP_KERNEL);
|
||||
if (sil == NULL)
|
||||
return false;
|
||||
|
||||
dvo->i2c_bus = adapter;
|
||||
dvo->dev_priv = sil;
|
||||
sil->quiet = true;
|
||||
|
||||
if (!sil164_readb(dvo, SIL164_VID_LO, &ch))
|
||||
goto out;
|
||||
|
||||
if (ch != (SIL164_VID & 0xff)) {
|
||||
DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
|
||||
ch, adapter->name, dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!sil164_readb(dvo, SIL164_DID_LO, &ch))
|
||||
goto out;
|
||||
|
||||
if (ch != (SIL164_DID & 0xff)) {
|
||||
DRM_DEBUG_KMS("sil164 not detected got %d: from %s Slave %d.\n",
|
||||
ch, adapter->name, dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
sil->quiet = false;
|
||||
|
||||
DRM_DEBUG_KMS("init sil164 dvo controller successfully!\n");
|
||||
return true;
|
||||
|
||||
out:
|
||||
kfree(sil);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo)
|
||||
{
|
||||
uint8_t reg9;
|
||||
|
||||
sil164_readb(dvo, SIL164_REG9, ®9);
|
||||
|
||||
if (reg9 & SIL164_9_HTPLG)
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void sil164_mode_set(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* As long as the basics are set up, since we don't have clock
|
||||
* dependencies in the mode setup, we can just leave the
|
||||
* registers alone and everything will work fine.
|
||||
*/
|
||||
/* recommended programming sequence from doc */
|
||||
/*sil164_writeb(sil, 0x08, 0x30);
|
||||
sil164_writeb(sil, 0x09, 0x00);
|
||||
sil164_writeb(sil, 0x0a, 0x90);
|
||||
sil164_writeb(sil, 0x0c, 0x89);
|
||||
sil164_writeb(sil, 0x08, 0x31);*/
|
||||
/* don't do much */
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the SIL164 power state */
|
||||
static void sil164_dpms(struct intel_dvo_device *dvo, int mode)
|
||||
{
|
||||
int ret;
|
||||
unsigned char ch;
|
||||
|
||||
ret = sil164_readb(dvo, SIL164_REG8, &ch);
|
||||
if (ret == false)
|
||||
return;
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
ch |= SIL164_8_PD;
|
||||
else
|
||||
ch &= ~SIL164_8_PD;
|
||||
|
||||
sil164_writeb(dvo, SIL164_REG8, ch);
|
||||
return;
|
||||
}
|
||||
|
||||
static void sil164_dump_regs(struct intel_dvo_device *dvo)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
sil164_readb(dvo, SIL164_FREQ_LO, &val);
|
||||
DRM_LOG_KMS("SIL164_FREQ_LO: 0x%02x\n", val);
|
||||
sil164_readb(dvo, SIL164_FREQ_HI, &val);
|
||||
DRM_LOG_KMS("SIL164_FREQ_HI: 0x%02x\n", val);
|
||||
sil164_readb(dvo, SIL164_REG8, &val);
|
||||
DRM_LOG_KMS("SIL164_REG8: 0x%02x\n", val);
|
||||
sil164_readb(dvo, SIL164_REG9, &val);
|
||||
DRM_LOG_KMS("SIL164_REG9: 0x%02x\n", val);
|
||||
sil164_readb(dvo, SIL164_REGC, &val);
|
||||
DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val);
|
||||
}
|
||||
|
||||
static void sil164_destroy(struct intel_dvo_device *dvo)
|
||||
{
|
||||
struct sil164_priv *sil = dvo->dev_priv;
|
||||
|
||||
if (sil) {
|
||||
kfree(sil);
|
||||
dvo->dev_priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops sil164_ops = {
|
||||
.init = sil164_init,
|
||||
.detect = sil164_detect,
|
||||
.mode_valid = sil164_mode_valid,
|
||||
.mode_set = sil164_mode_set,
|
||||
.dpms = sil164_dpms,
|
||||
.dump_regs = sil164_dump_regs,
|
||||
.destroy = sil164_destroy,
|
||||
};
|
304
drivers/video/drm/i915/dvo_tfp410.c
Normal file
304
drivers/video/drm/i915/dvo_tfp410.c
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright © 2007 Dave Mueller
|
||||
*
|
||||
* 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:
|
||||
* Dave Mueller <dave.mueller@gmx.ch>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
|
||||
/* register definitions according to the TFP410 data sheet */
|
||||
#define TFP410_VID 0x014C
|
||||
#define TFP410_DID 0x0410
|
||||
|
||||
#define TFP410_VID_LO 0x00
|
||||
#define TFP410_VID_HI 0x01
|
||||
#define TFP410_DID_LO 0x02
|
||||
#define TFP410_DID_HI 0x03
|
||||
#define TFP410_REV 0x04
|
||||
|
||||
#define TFP410_CTL_1 0x08
|
||||
#define TFP410_CTL_1_TDIS (1<<6)
|
||||
#define TFP410_CTL_1_VEN (1<<5)
|
||||
#define TFP410_CTL_1_HEN (1<<4)
|
||||
#define TFP410_CTL_1_DSEL (1<<3)
|
||||
#define TFP410_CTL_1_BSEL (1<<2)
|
||||
#define TFP410_CTL_1_EDGE (1<<1)
|
||||
#define TFP410_CTL_1_PD (1<<0)
|
||||
|
||||
#define TFP410_CTL_2 0x09
|
||||
#define TFP410_CTL_2_VLOW (1<<7)
|
||||
#define TFP410_CTL_2_MSEL_MASK (0x7<<4)
|
||||
#define TFP410_CTL_2_MSEL (1<<4)
|
||||
#define TFP410_CTL_2_TSEL (1<<3)
|
||||
#define TFP410_CTL_2_RSEN (1<<2)
|
||||
#define TFP410_CTL_2_HTPLG (1<<1)
|
||||
#define TFP410_CTL_2_MDI (1<<0)
|
||||
|
||||
#define TFP410_CTL_3 0x0A
|
||||
#define TFP410_CTL_3_DK_MASK (0x7<<5)
|
||||
#define TFP410_CTL_3_DK (1<<5)
|
||||
#define TFP410_CTL_3_DKEN (1<<4)
|
||||
#define TFP410_CTL_3_CTL_MASK (0x7<<1)
|
||||
#define TFP410_CTL_3_CTL (1<<1)
|
||||
|
||||
#define TFP410_USERCFG 0x0B
|
||||
|
||||
#define TFP410_DE_DLY 0x32
|
||||
|
||||
#define TFP410_DE_CTL 0x33
|
||||
#define TFP410_DE_CTL_DEGEN (1<<6)
|
||||
#define TFP410_DE_CTL_VSPOL (1<<5)
|
||||
#define TFP410_DE_CTL_HSPOL (1<<4)
|
||||
#define TFP410_DE_CTL_DEDLY8 (1<<0)
|
||||
|
||||
#define TFP410_DE_TOP 0x34
|
||||
|
||||
#define TFP410_DE_CNT_LO 0x36
|
||||
#define TFP410_DE_CNT_HI 0x37
|
||||
|
||||
#define TFP410_DE_LIN_LO 0x38
|
||||
#define TFP410_DE_LIN_HI 0x39
|
||||
|
||||
#define TFP410_H_RES_LO 0x3A
|
||||
#define TFP410_H_RES_HI 0x3B
|
||||
|
||||
#define TFP410_V_RES_LO 0x3C
|
||||
#define TFP410_V_RES_HI 0x3D
|
||||
|
||||
struct tfp410_priv {
|
||||
bool quiet;
|
||||
};
|
||||
|
||||
static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
||||
{
|
||||
struct tfp410_priv *tfp = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
u8 out_buf[2];
|
||||
u8 in_buf[2];
|
||||
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = in_buf,
|
||||
}
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = 0;
|
||||
|
||||
if (i2c_transfer(adapter, msgs, 2) == 2) {
|
||||
*ch = in_buf[0];
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!tfp->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to read register 0x%02x from %s:%02x.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
|
||||
{
|
||||
struct tfp410_priv *tfp = dvo->dev_priv;
|
||||
struct i2c_adapter *adapter = dvo->i2c_bus;
|
||||
uint8_t out_buf[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = dvo->slave_addr,
|
||||
.flags = 0,
|
||||
.len = 2,
|
||||
.buf = out_buf,
|
||||
};
|
||||
|
||||
out_buf[0] = addr;
|
||||
out_buf[1] = ch;
|
||||
|
||||
if (i2c_transfer(adapter, &msg, 1) == 1)
|
||||
return true;
|
||||
|
||||
if (!tfp->quiet) {
|
||||
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
|
||||
addr, adapter->name, dvo->slave_addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tfp410_getid(struct intel_dvo_device *dvo, int addr)
|
||||
{
|
||||
uint8_t ch1, ch2;
|
||||
|
||||
if (tfp410_readb(dvo, addr+0, &ch1) &&
|
||||
tfp410_readb(dvo, addr+1, &ch2))
|
||||
return ((ch2 << 8) & 0xFF00) | (ch1 & 0x00FF);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ti TFP410 driver for chip on i2c bus */
|
||||
static bool tfp410_init(struct intel_dvo_device *dvo,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
/* this will detect the tfp410 chip on the specified i2c bus */
|
||||
struct tfp410_priv *tfp;
|
||||
int id;
|
||||
|
||||
tfp = kzalloc(sizeof(struct tfp410_priv), GFP_KERNEL);
|
||||
if (tfp == NULL)
|
||||
return false;
|
||||
|
||||
dvo->i2c_bus = adapter;
|
||||
dvo->dev_priv = tfp;
|
||||
tfp->quiet = true;
|
||||
|
||||
if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
|
||||
DRM_DEBUG_KMS("tfp410 not detected got VID %X: from %s "
|
||||
"Slave %d.\n",
|
||||
id, adapter->name, dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
|
||||
DRM_DEBUG_KMS("tfp410 not detected got DID %X: from %s "
|
||||
"Slave %d.\n",
|
||||
id, adapter->name, dvo->slave_addr);
|
||||
goto out;
|
||||
}
|
||||
tfp->quiet = false;
|
||||
return true;
|
||||
out:
|
||||
kfree(tfp);
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)
|
||||
{
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
uint8_t ctl2;
|
||||
|
||||
if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
|
||||
if (ctl2 & TFP410_CTL_2_RSEN)
|
||||
ret = connector_status_connected;
|
||||
else
|
||||
ret = connector_status_disconnected;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum drm_mode_status tfp410_mode_valid(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void tfp410_mode_set(struct intel_dvo_device *dvo,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* As long as the basics are set up, since we don't have clock dependencies
|
||||
* in the mode setup, we can just leave the registers alone and everything
|
||||
* will work fine.
|
||||
*/
|
||||
/* don't do much */
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the tfp410 power state */
|
||||
static void tfp410_dpms(struct intel_dvo_device *dvo, int mode)
|
||||
{
|
||||
uint8_t ctl1;
|
||||
|
||||
if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
|
||||
return;
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON)
|
||||
ctl1 |= TFP410_CTL_1_PD;
|
||||
else
|
||||
ctl1 &= ~TFP410_CTL_1_PD;
|
||||
|
||||
tfp410_writeb(dvo, TFP410_CTL_1, ctl1);
|
||||
}
|
||||
|
||||
static void tfp410_dump_regs(struct intel_dvo_device *dvo)
|
||||
{
|
||||
uint8_t val, val2;
|
||||
|
||||
tfp410_readb(dvo, TFP410_REV, &val);
|
||||
DRM_LOG_KMS("TFP410_REV: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_CTL_1, &val);
|
||||
DRM_LOG_KMS("TFP410_CTL1: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_CTL_2, &val);
|
||||
DRM_LOG_KMS("TFP410_CTL2: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_CTL_3, &val);
|
||||
DRM_LOG_KMS("TFP410_CTL3: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_USERCFG, &val);
|
||||
DRM_LOG_KMS("TFP410_USERCFG: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_DE_DLY, &val);
|
||||
DRM_LOG_KMS("TFP410_DE_DLY: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_DE_CTL, &val);
|
||||
DRM_LOG_KMS("TFP410_DE_CTL: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_DE_TOP, &val);
|
||||
DRM_LOG_KMS("TFP410_DE_TOP: 0x%02X\n", val);
|
||||
tfp410_readb(dvo, TFP410_DE_CNT_LO, &val);
|
||||
tfp410_readb(dvo, TFP410_DE_CNT_HI, &val2);
|
||||
DRM_LOG_KMS("TFP410_DE_CNT: 0x%02X%02X\n", val2, val);
|
||||
tfp410_readb(dvo, TFP410_DE_LIN_LO, &val);
|
||||
tfp410_readb(dvo, TFP410_DE_LIN_HI, &val2);
|
||||
DRM_LOG_KMS("TFP410_DE_LIN: 0x%02X%02X\n", val2, val);
|
||||
tfp410_readb(dvo, TFP410_H_RES_LO, &val);
|
||||
tfp410_readb(dvo, TFP410_H_RES_HI, &val2);
|
||||
DRM_LOG_KMS("TFP410_H_RES: 0x%02X%02X\n", val2, val);
|
||||
tfp410_readb(dvo, TFP410_V_RES_LO, &val);
|
||||
tfp410_readb(dvo, TFP410_V_RES_HI, &val2);
|
||||
DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
|
||||
}
|
||||
|
||||
static void tfp410_destroy(struct intel_dvo_device *dvo)
|
||||
{
|
||||
struct tfp410_priv *tfp = dvo->dev_priv;
|
||||
|
||||
if (tfp) {
|
||||
kfree(tfp);
|
||||
dvo->dev_priv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops tfp410_ops = {
|
||||
.init = tfp410_init,
|
||||
.detect = tfp410_detect,
|
||||
.mode_valid = tfp410_mode_valid,
|
||||
.mode_set = tfp410_mode_set,
|
||||
.dpms = tfp410_dpms,
|
||||
.dump_regs = tfp410_dump_regs,
|
||||
.destroy = tfp410_destroy,
|
||||
};
|
@ -31,7 +31,7 @@
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "drm_fb_helper.h"
|
||||
#include "intel_drv.h"
|
||||
//#include "i915_drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include <drm/intel-gtt.h>
|
||||
//#include "i915_trace.h"
|
||||
@ -41,11 +41,20 @@
|
||||
//#include <linux/acpi.h>
|
||||
//#include <linux/pnp.h>
|
||||
//#include <linux/vga_switcheroo.h>
|
||||
//#include <linux/slab.h>
|
||||
#include <linux/slab.h>
|
||||
//#include <acpi/video.h>
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen);
|
||||
|
||||
static inline int pci_read_config_dword(struct pci_dev *dev, int where,
|
||||
u32 *val)
|
||||
{
|
||||
*val = PciRead32(dev->busnr, dev->devfn, where);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void i915_write_hws_pga(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
@ -57,7 +66,6 @@ static void i915_write_hws_pga(struct drm_device *dev)
|
||||
I915_WRITE(HWS_PGA, addr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets up the hardware status page for devices that need a physical address
|
||||
* in the register.
|
||||
@ -81,6 +89,136 @@ static int i915_init_phys_hws(struct drm_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define MCHBAR_I915 0x44
|
||||
#define MCHBAR_I965 0x48
|
||||
#define MCHBAR_SIZE (4*4096)
|
||||
|
||||
#define DEVEN_REG 0x54
|
||||
#define DEVEN_MCHBAR_EN (1 << 28)
|
||||
|
||||
|
||||
|
||||
|
||||
/* Setup MCHBAR if possible, return true if we should disable it again */
|
||||
static void
|
||||
intel_setup_mchbar(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
dev_priv->mchbar_need_disable = false;
|
||||
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
||||
enabled = !!(temp & DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
enabled = temp & 1;
|
||||
}
|
||||
|
||||
/* If it's already enabled, don't have to do anything */
|
||||
if (enabled)
|
||||
return;
|
||||
|
||||
dbgprintf("Epic fail\n");
|
||||
|
||||
#if 0
|
||||
if (intel_alloc_mchbar_resource(dev))
|
||||
return;
|
||||
|
||||
dev_priv->mchbar_need_disable = true;
|
||||
|
||||
/* Space is allocated or reserved, so enable it. */
|
||||
if (IS_I915G(dev) || IS_I915GM(dev)) {
|
||||
pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
|
||||
temp | DEVEN_MCHBAR_EN);
|
||||
} else {
|
||||
pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
||||
pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int i915_load_gem_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned long prealloc_size, gtt_size, mappable_size;
|
||||
int ret;
|
||||
|
||||
prealloc_size = dev_priv->mm.gtt->stolen_size;
|
||||
gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
|
||||
mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
|
||||
|
||||
dbgprintf("%s prealloc: %x gtt: %x mappable: %x\n",__FUNCTION__,
|
||||
prealloc_size, gtt_size, mappable_size);
|
||||
|
||||
/* Basic memrange allocator for stolen space */
|
||||
drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
|
||||
|
||||
//0xC00000 >> PAGE_SHIFT
|
||||
|
||||
/* Let GEM Manage all of the aperture.
|
||||
*
|
||||
* However, leave one page at the end still bound to the scratch page.
|
||||
* There are a number of places where the hardware apparently
|
||||
* prefetches past the end of the object, and we've seen multiple
|
||||
* hangs with the GPU head pointer stuck in a batchbuffer bound
|
||||
* at the last page of the aperture. One page should be enough to
|
||||
* keep any prefetching inside of the aperture.
|
||||
*/
|
||||
// i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE);
|
||||
|
||||
// mutex_lock(&dev->struct_mutex);
|
||||
// ret = i915_gem_init_ringbuffer(dev);
|
||||
// mutex_unlock(&dev->struct_mutex);
|
||||
// if (ret)
|
||||
// return ret;
|
||||
|
||||
/* Try to set up FBC with a reasonable compressed buffer size */
|
||||
// if (I915_HAS_FBC(dev) && i915_powersave) {
|
||||
// int cfb_size;
|
||||
|
||||
/* Leave 1M for line length buffer & misc. */
|
||||
|
||||
/* Try to get a 32M buffer... */
|
||||
// if (prealloc_size > (36*1024*1024))
|
||||
// cfb_size = 32*1024*1024;
|
||||
// else /* fall back to 7/8 of the stolen space */
|
||||
// cfb_size = prealloc_size * 7 / 8;
|
||||
// i915_setup_compression(dev, cfb_size);
|
||||
// }
|
||||
|
||||
/* Allow hardware batchbuffers unless told otherwise. */
|
||||
dev_priv->allow_batchbuffer = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_load_modeset_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
@ -98,12 +236,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
|
||||
intel_modeset_init(dev);
|
||||
|
||||
#if 0
|
||||
|
||||
ret = i915_load_gem_init(dev);
|
||||
if (ret)
|
||||
goto cleanup_vga_switcheroo;
|
||||
|
||||
#if 0
|
||||
|
||||
intel_modeset_gem_init(dev);
|
||||
|
||||
ret = drm_irq_install(dev);
|
||||
@ -392,13 +530,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
// intel_irq_init(dev);
|
||||
|
||||
/* Try to make sure MCHBAR is enabled before poking at it */
|
||||
// intel_setup_mchbar(dev);
|
||||
intel_setup_mchbar(dev);
|
||||
intel_setup_gmbus(dev);
|
||||
|
||||
intel_opregion_setup(dev);
|
||||
|
||||
/* Make sure the bios did its job and set up vital registers */
|
||||
// intel_setup_bios(dev);
|
||||
intel_setup_bios(dev);
|
||||
|
||||
i915_gem_load(dev);
|
||||
|
||||
|
847
drivers/video/drm/i915/i915_drm.h
Normal file
847
drivers/video/drm/i915/i915_drm.h
Normal file
@ -0,0 +1,847 @@
|
||||
/*
|
||||
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _I915_DRM_H_
|
||||
#define _I915_DRM_H_
|
||||
|
||||
#include "drm.h"
|
||||
|
||||
/* Please note that modifications to all structs defined here are
|
||||
* subject to backwards-compatibility constraints.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
/* For use by IPS driver */
|
||||
extern unsigned long i915_read_mch_val(void);
|
||||
extern bool i915_gpu_raise(void);
|
||||
extern bool i915_gpu_lower(void);
|
||||
extern bool i915_gpu_busy(void);
|
||||
extern bool i915_gpu_turbo_disable(void);
|
||||
#endif
|
||||
|
||||
/* Each region is a minimum of 16k, and there are at most 255 of them.
|
||||
*/
|
||||
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
|
||||
* of chars for next/prev indices */
|
||||
#define I915_LOG_MIN_TEX_REGION_SIZE 14
|
||||
|
||||
typedef struct _drm_i915_init {
|
||||
enum {
|
||||
I915_INIT_DMA = 0x01,
|
||||
I915_CLEANUP_DMA = 0x02,
|
||||
I915_RESUME_DMA = 0x03
|
||||
} func;
|
||||
unsigned int mmio_offset;
|
||||
int sarea_priv_offset;
|
||||
unsigned int ring_start;
|
||||
unsigned int ring_end;
|
||||
unsigned int ring_size;
|
||||
unsigned int front_offset;
|
||||
unsigned int back_offset;
|
||||
unsigned int depth_offset;
|
||||
unsigned int w;
|
||||
unsigned int h;
|
||||
unsigned int pitch;
|
||||
unsigned int pitch_bits;
|
||||
unsigned int back_pitch;
|
||||
unsigned int depth_pitch;
|
||||
unsigned int cpp;
|
||||
unsigned int chipset;
|
||||
} drm_i915_init_t;
|
||||
|
||||
typedef struct _drm_i915_sarea {
|
||||
struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1];
|
||||
int last_upload; /* last time texture was uploaded */
|
||||
int last_enqueue; /* last time a buffer was enqueued */
|
||||
int last_dispatch; /* age of the most recently dispatched buffer */
|
||||
int ctxOwner; /* last context to upload state */
|
||||
int texAge;
|
||||
int pf_enabled; /* is pageflipping allowed? */
|
||||
int pf_active;
|
||||
int pf_current_page; /* which buffer is being displayed? */
|
||||
int perf_boxes; /* performance boxes to be displayed */
|
||||
int width, height; /* screen size in pixels */
|
||||
|
||||
drm_handle_t front_handle;
|
||||
int front_offset;
|
||||
int front_size;
|
||||
|
||||
drm_handle_t back_handle;
|
||||
int back_offset;
|
||||
int back_size;
|
||||
|
||||
drm_handle_t depth_handle;
|
||||
int depth_offset;
|
||||
int depth_size;
|
||||
|
||||
drm_handle_t tex_handle;
|
||||
int tex_offset;
|
||||
int tex_size;
|
||||
int log_tex_granularity;
|
||||
int pitch;
|
||||
int rotation; /* 0, 90, 180 or 270 */
|
||||
int rotated_offset;
|
||||
int rotated_size;
|
||||
int rotated_pitch;
|
||||
int virtualX, virtualY;
|
||||
|
||||
unsigned int front_tiled;
|
||||
unsigned int back_tiled;
|
||||
unsigned int depth_tiled;
|
||||
unsigned int rotated_tiled;
|
||||
unsigned int rotated2_tiled;
|
||||
|
||||
int pipeA_x;
|
||||
int pipeA_y;
|
||||
int pipeA_w;
|
||||
int pipeA_h;
|
||||
int pipeB_x;
|
||||
int pipeB_y;
|
||||
int pipeB_w;
|
||||
int pipeB_h;
|
||||
|
||||
/* fill out some space for old userspace triple buffer */
|
||||
drm_handle_t unused_handle;
|
||||
__u32 unused1, unused2, unused3;
|
||||
|
||||
/* buffer object handles for static buffers. May change
|
||||
* over the lifetime of the client.
|
||||
*/
|
||||
__u32 front_bo_handle;
|
||||
__u32 back_bo_handle;
|
||||
__u32 unused_bo_handle;
|
||||
__u32 depth_bo_handle;
|
||||
|
||||
} drm_i915_sarea_t;
|
||||
|
||||
/* due to userspace building against these headers we need some compat here */
|
||||
#define planeA_x pipeA_x
|
||||
#define planeA_y pipeA_y
|
||||
#define planeA_w pipeA_w
|
||||
#define planeA_h pipeA_h
|
||||
#define planeB_x pipeB_x
|
||||
#define planeB_y pipeB_y
|
||||
#define planeB_w pipeB_w
|
||||
#define planeB_h pipeB_h
|
||||
|
||||
/* Flags for perf_boxes
|
||||
*/
|
||||
#define I915_BOX_RING_EMPTY 0x1
|
||||
#define I915_BOX_FLIP 0x2
|
||||
#define I915_BOX_WAIT 0x4
|
||||
#define I915_BOX_TEXTURE_LOAD 0x8
|
||||
#define I915_BOX_LOST_CONTEXT 0x10
|
||||
|
||||
/* I915 specific ioctls
|
||||
* The device specific ioctl range is 0x40 to 0x79.
|
||||
*/
|
||||
#define DRM_I915_INIT 0x00
|
||||
#define DRM_I915_FLUSH 0x01
|
||||
#define DRM_I915_FLIP 0x02
|
||||
#define DRM_I915_BATCHBUFFER 0x03
|
||||
#define DRM_I915_IRQ_EMIT 0x04
|
||||
#define DRM_I915_IRQ_WAIT 0x05
|
||||
#define DRM_I915_GETPARAM 0x06
|
||||
#define DRM_I915_SETPARAM 0x07
|
||||
#define DRM_I915_ALLOC 0x08
|
||||
#define DRM_I915_FREE 0x09
|
||||
#define DRM_I915_INIT_HEAP 0x0a
|
||||
#define DRM_I915_CMDBUFFER 0x0b
|
||||
#define DRM_I915_DESTROY_HEAP 0x0c
|
||||
#define DRM_I915_SET_VBLANK_PIPE 0x0d
|
||||
#define DRM_I915_GET_VBLANK_PIPE 0x0e
|
||||
#define DRM_I915_VBLANK_SWAP 0x0f
|
||||
#define DRM_I915_HWS_ADDR 0x11
|
||||
#define DRM_I915_GEM_INIT 0x13
|
||||
#define DRM_I915_GEM_EXECBUFFER 0x14
|
||||
#define DRM_I915_GEM_PIN 0x15
|
||||
#define DRM_I915_GEM_UNPIN 0x16
|
||||
#define DRM_I915_GEM_BUSY 0x17
|
||||
#define DRM_I915_GEM_THROTTLE 0x18
|
||||
#define DRM_I915_GEM_ENTERVT 0x19
|
||||
#define DRM_I915_GEM_LEAVEVT 0x1a
|
||||
#define DRM_I915_GEM_CREATE 0x1b
|
||||
#define DRM_I915_GEM_PREAD 0x1c
|
||||
#define DRM_I915_GEM_PWRITE 0x1d
|
||||
#define DRM_I915_GEM_MMAP 0x1e
|
||||
#define DRM_I915_GEM_SET_DOMAIN 0x1f
|
||||
#define DRM_I915_GEM_SW_FINISH 0x20
|
||||
#define DRM_I915_GEM_SET_TILING 0x21
|
||||
#define DRM_I915_GEM_GET_TILING 0x22
|
||||
#define DRM_I915_GEM_GET_APERTURE 0x23
|
||||
#define DRM_I915_GEM_MMAP_GTT 0x24
|
||||
#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25
|
||||
#define DRM_I915_GEM_MADVISE 0x26
|
||||
#define DRM_I915_OVERLAY_PUT_IMAGE 0x27
|
||||
#define DRM_I915_OVERLAY_ATTRS 0x28
|
||||
#define DRM_I915_GEM_EXECBUFFER2 0x29
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
|
||||
#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
|
||||
#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
|
||||
#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
|
||||
#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t)
|
||||
#define DRM_IOCTL_I915_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SETPARAM, drm_i915_setparam_t)
|
||||
#define DRM_IOCTL_I915_ALLOC DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_ALLOC, drm_i915_mem_alloc_t)
|
||||
#define DRM_IOCTL_I915_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FREE, drm_i915_mem_free_t)
|
||||
#define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
|
||||
#define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
|
||||
#define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
|
||||
#define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
|
||||
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
|
||||
#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
|
||||
#define DRM_IOCTL_I915_HWS_ADDR DRM_IOW(DRM_COMMAND_BASE + DRM_I915_HWS_ADDR, struct drm_i915_gem_init)
|
||||
#define DRM_IOCTL_I915_GEM_INIT DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_INIT, struct drm_i915_gem_init)
|
||||
#define DRM_IOCTL_I915_GEM_EXECBUFFER DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER, struct drm_i915_gem_execbuffer)
|
||||
#define DRM_IOCTL_I915_GEM_EXECBUFFER2 DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2)
|
||||
#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
|
||||
#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
|
||||
#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
|
||||
#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
|
||||
#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
|
||||
#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
|
||||
#define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create)
|
||||
#define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread)
|
||||
#define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite)
|
||||
#define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap)
|
||||
#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt)
|
||||
#define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain)
|
||||
#define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
|
||||
#define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
|
||||
#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
|
||||
#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
|
||||
#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
|
||||
#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
|
||||
#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
|
||||
#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
*/
|
||||
typedef struct drm_i915_batchbuffer {
|
||||
int start; /* agp offset */
|
||||
int used; /* nr bytes in use */
|
||||
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
|
||||
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
|
||||
int num_cliprects; /* mulitpass with multiple cliprects? */
|
||||
struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
|
||||
} drm_i915_batchbuffer_t;
|
||||
|
||||
/* As above, but pass a pointer to userspace buffer which can be
|
||||
* validated by the kernel prior to sending to hardware.
|
||||
*/
|
||||
typedef struct _drm_i915_cmdbuffer {
|
||||
char __user *buf; /* pointer to userspace command buffer */
|
||||
int sz; /* nr bytes in buf */
|
||||
int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
|
||||
int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
|
||||
int num_cliprects; /* mulitpass with multiple cliprects? */
|
||||
struct drm_clip_rect __user *cliprects; /* pointer to userspace cliprects */
|
||||
} drm_i915_cmdbuffer_t;
|
||||
|
||||
/* Userspace can request & wait on irq's:
|
||||
*/
|
||||
typedef struct drm_i915_irq_emit {
|
||||
int __user *irq_seq;
|
||||
} drm_i915_irq_emit_t;
|
||||
|
||||
typedef struct drm_i915_irq_wait {
|
||||
int irq_seq;
|
||||
} drm_i915_irq_wait_t;
|
||||
|
||||
/* Ioctl to query kernel params:
|
||||
*/
|
||||
#define I915_PARAM_IRQ_ACTIVE 1
|
||||
#define I915_PARAM_ALLOW_BATCHBUFFER 2
|
||||
#define I915_PARAM_LAST_DISPATCH 3
|
||||
#define I915_PARAM_CHIPSET_ID 4
|
||||
#define I915_PARAM_HAS_GEM 5
|
||||
#define I915_PARAM_NUM_FENCES_AVAIL 6
|
||||
#define I915_PARAM_HAS_OVERLAY 7
|
||||
#define I915_PARAM_HAS_PAGEFLIPPING 8
|
||||
#define I915_PARAM_HAS_EXECBUF2 9
|
||||
#define I915_PARAM_HAS_BSD 10
|
||||
#define I915_PARAM_HAS_BLT 11
|
||||
#define I915_PARAM_HAS_RELAXED_FENCING 12
|
||||
#define I915_PARAM_HAS_COHERENT_RINGS 13
|
||||
#define I915_PARAM_HAS_EXEC_CONSTANTS 14
|
||||
#define I915_PARAM_HAS_RELAXED_DELTA 15
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
int param;
|
||||
int __user *value;
|
||||
} drm_i915_getparam_t;
|
||||
|
||||
/* Ioctl to set kernel params:
|
||||
*/
|
||||
#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1
|
||||
#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
|
||||
#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
|
||||
#define I915_SETPARAM_NUM_USED_FENCES 4
|
||||
|
||||
typedef struct drm_i915_setparam {
|
||||
int param;
|
||||
int value;
|
||||
} drm_i915_setparam_t;
|
||||
|
||||
/* A memory manager for regions of shared memory:
|
||||
*/
|
||||
#define I915_MEM_REGION_AGP 1
|
||||
|
||||
typedef struct drm_i915_mem_alloc {
|
||||
int region;
|
||||
int alignment;
|
||||
int size;
|
||||
int __user *region_offset; /* offset from start of fb or agp */
|
||||
} drm_i915_mem_alloc_t;
|
||||
|
||||
typedef struct drm_i915_mem_free {
|
||||
int region;
|
||||
int region_offset;
|
||||
} drm_i915_mem_free_t;
|
||||
|
||||
typedef struct drm_i915_mem_init_heap {
|
||||
int region;
|
||||
int size;
|
||||
int start;
|
||||
} drm_i915_mem_init_heap_t;
|
||||
|
||||
/* Allow memory manager to be torn down and re-initialized (eg on
|
||||
* rotate):
|
||||
*/
|
||||
typedef struct drm_i915_mem_destroy_heap {
|
||||
int region;
|
||||
} drm_i915_mem_destroy_heap_t;
|
||||
|
||||
/* Allow X server to configure which pipes to monitor for vblank signals
|
||||
*/
|
||||
#define DRM_I915_VBLANK_PIPE_A 1
|
||||
#define DRM_I915_VBLANK_PIPE_B 2
|
||||
|
||||
typedef struct drm_i915_vblank_pipe {
|
||||
int pipe;
|
||||
} drm_i915_vblank_pipe_t;
|
||||
|
||||
/* Schedule buffer swap at given vertical blank:
|
||||
*/
|
||||
typedef struct drm_i915_vblank_swap {
|
||||
drm_drawable_t drawable;
|
||||
enum drm_vblank_seq_type seqtype;
|
||||
unsigned int sequence;
|
||||
} drm_i915_vblank_swap_t;
|
||||
|
||||
typedef struct drm_i915_hws_addr {
|
||||
__u64 addr;
|
||||
} drm_i915_hws_addr_t;
|
||||
|
||||
struct drm_i915_gem_init {
|
||||
/**
|
||||
* Beginning offset in the GTT to be managed by the DRM memory
|
||||
* manager.
|
||||
*/
|
||||
__u64 gtt_start;
|
||||
/**
|
||||
* Ending offset in the GTT to be managed by the DRM memory
|
||||
* manager.
|
||||
*/
|
||||
__u64 gtt_end;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_create {
|
||||
/**
|
||||
* Requested size for the object.
|
||||
*
|
||||
* The (page-aligned) allocated size for the object will be returned.
|
||||
*/
|
||||
__u64 size;
|
||||
/**
|
||||
* Returned handle for the object.
|
||||
*
|
||||
* Object handles are nonzero.
|
||||
*/
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_pread {
|
||||
/** Handle for the object being read. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
/** Offset into the object to read from */
|
||||
__u64 offset;
|
||||
/** Length of data to read */
|
||||
__u64 size;
|
||||
/**
|
||||
* Pointer to write the data into.
|
||||
*
|
||||
* This is a fixed-size type for 32/64 compatibility.
|
||||
*/
|
||||
__u64 data_ptr;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_pwrite {
|
||||
/** Handle for the object being written to. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
/** Offset into the object to write to */
|
||||
__u64 offset;
|
||||
/** Length of data to write */
|
||||
__u64 size;
|
||||
/**
|
||||
* Pointer to read the data from.
|
||||
*
|
||||
* This is a fixed-size type for 32/64 compatibility.
|
||||
*/
|
||||
__u64 data_ptr;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_mmap {
|
||||
/** Handle for the object being mapped. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
/** Offset in the object to map. */
|
||||
__u64 offset;
|
||||
/**
|
||||
* Length of data to map.
|
||||
*
|
||||
* The value will be page-aligned.
|
||||
*/
|
||||
__u64 size;
|
||||
/**
|
||||
* Returned pointer the data was mapped at.
|
||||
*
|
||||
* This is a fixed-size type for 32/64 compatibility.
|
||||
*/
|
||||
__u64 addr_ptr;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_mmap_gtt {
|
||||
/** Handle for the object being mapped. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
/**
|
||||
* Fake offset to use for subsequent mmap call
|
||||
*
|
||||
* This is a fixed-size type for 32/64 compatibility.
|
||||
*/
|
||||
__u64 offset;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_set_domain {
|
||||
/** Handle for the object */
|
||||
__u32 handle;
|
||||
|
||||
/** New read domains */
|
||||
__u32 read_domains;
|
||||
|
||||
/** New write domain */
|
||||
__u32 write_domain;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_sw_finish {
|
||||
/** Handle for the object */
|
||||
__u32 handle;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_relocation_entry {
|
||||
/**
|
||||
* Handle of the buffer being pointed to by this relocation entry.
|
||||
*
|
||||
* It's appealing to make this be an index into the mm_validate_entry
|
||||
* list to refer to the buffer, but this allows the driver to create
|
||||
* a relocation list for state buffers and not re-write it per
|
||||
* exec using the buffer.
|
||||
*/
|
||||
__u32 target_handle;
|
||||
|
||||
/**
|
||||
* Value to be added to the offset of the target buffer to make up
|
||||
* the relocation entry.
|
||||
*/
|
||||
__u32 delta;
|
||||
|
||||
/** Offset in the buffer the relocation entry will be written into */
|
||||
__u64 offset;
|
||||
|
||||
/**
|
||||
* Offset value of the target buffer that the relocation entry was last
|
||||
* written as.
|
||||
*
|
||||
* If the buffer has the same offset as last time, we can skip syncing
|
||||
* and writing the relocation. This value is written back out by
|
||||
* the execbuffer ioctl when the relocation is written.
|
||||
*/
|
||||
__u64 presumed_offset;
|
||||
|
||||
/**
|
||||
* Target memory domains read by this operation.
|
||||
*/
|
||||
__u32 read_domains;
|
||||
|
||||
/**
|
||||
* Target memory domains written by this operation.
|
||||
*
|
||||
* Note that only one domain may be written by the whole
|
||||
* execbuffer operation, so that where there are conflicts,
|
||||
* the application will get -EINVAL back.
|
||||
*/
|
||||
__u32 write_domain;
|
||||
};
|
||||
|
||||
/** @{
|
||||
* Intel memory domains
|
||||
*
|
||||
* Most of these just align with the various caches in
|
||||
* the system and are used to flush and invalidate as
|
||||
* objects end up cached in different domains.
|
||||
*/
|
||||
/** CPU cache */
|
||||
#define I915_GEM_DOMAIN_CPU 0x00000001
|
||||
/** Render cache, used by 2D and 3D drawing */
|
||||
#define I915_GEM_DOMAIN_RENDER 0x00000002
|
||||
/** Sampler cache, used by texture engine */
|
||||
#define I915_GEM_DOMAIN_SAMPLER 0x00000004
|
||||
/** Command queue, used to load batch buffers */
|
||||
#define I915_GEM_DOMAIN_COMMAND 0x00000008
|
||||
/** Instruction cache, used by shader programs */
|
||||
#define I915_GEM_DOMAIN_INSTRUCTION 0x00000010
|
||||
/** Vertex address cache */
|
||||
#define I915_GEM_DOMAIN_VERTEX 0x00000020
|
||||
/** GTT domain - aperture and scanout */
|
||||
#define I915_GEM_DOMAIN_GTT 0x00000040
|
||||
/** @} */
|
||||
|
||||
struct drm_i915_gem_exec_object {
|
||||
/**
|
||||
* User's handle for a buffer to be bound into the GTT for this
|
||||
* operation.
|
||||
*/
|
||||
__u32 handle;
|
||||
|
||||
/** Number of relocations to be performed on this buffer */
|
||||
__u32 relocation_count;
|
||||
/**
|
||||
* Pointer to array of struct drm_i915_gem_relocation_entry containing
|
||||
* the relocations to be performed in this buffer.
|
||||
*/
|
||||
__u64 relocs_ptr;
|
||||
|
||||
/** Required alignment in graphics aperture */
|
||||
__u64 alignment;
|
||||
|
||||
/**
|
||||
* Returned value of the updated offset of the object, for future
|
||||
* presumed_offset writes.
|
||||
*/
|
||||
__u64 offset;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_execbuffer {
|
||||
/**
|
||||
* List of buffers to be validated with their relocations to be
|
||||
* performend on them.
|
||||
*
|
||||
* This is a pointer to an array of struct drm_i915_gem_validate_entry.
|
||||
*
|
||||
* These buffers must be listed in an order such that all relocations
|
||||
* a buffer is performing refer to buffers that have already appeared
|
||||
* in the validate list.
|
||||
*/
|
||||
__u64 buffers_ptr;
|
||||
__u32 buffer_count;
|
||||
|
||||
/** Offset in the batchbuffer to start execution from. */
|
||||
__u32 batch_start_offset;
|
||||
/** Bytes used in batchbuffer from batch_start_offset */
|
||||
__u32 batch_len;
|
||||
__u32 DR1;
|
||||
__u32 DR4;
|
||||
__u32 num_cliprects;
|
||||
/** This is a struct drm_clip_rect *cliprects */
|
||||
__u64 cliprects_ptr;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_exec_object2 {
|
||||
/**
|
||||
* User's handle for a buffer to be bound into the GTT for this
|
||||
* operation.
|
||||
*/
|
||||
__u32 handle;
|
||||
|
||||
/** Number of relocations to be performed on this buffer */
|
||||
__u32 relocation_count;
|
||||
/**
|
||||
* Pointer to array of struct drm_i915_gem_relocation_entry containing
|
||||
* the relocations to be performed in this buffer.
|
||||
*/
|
||||
__u64 relocs_ptr;
|
||||
|
||||
/** Required alignment in graphics aperture */
|
||||
__u64 alignment;
|
||||
|
||||
/**
|
||||
* Returned value of the updated offset of the object, for future
|
||||
* presumed_offset writes.
|
||||
*/
|
||||
__u64 offset;
|
||||
|
||||
#define EXEC_OBJECT_NEEDS_FENCE (1<<0)
|
||||
__u64 flags;
|
||||
__u64 rsvd1;
|
||||
__u64 rsvd2;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_execbuffer2 {
|
||||
/**
|
||||
* List of gem_exec_object2 structs
|
||||
*/
|
||||
__u64 buffers_ptr;
|
||||
__u32 buffer_count;
|
||||
|
||||
/** Offset in the batchbuffer to start execution from. */
|
||||
__u32 batch_start_offset;
|
||||
/** Bytes used in batchbuffer from batch_start_offset */
|
||||
__u32 batch_len;
|
||||
__u32 DR1;
|
||||
__u32 DR4;
|
||||
__u32 num_cliprects;
|
||||
/** This is a struct drm_clip_rect *cliprects */
|
||||
__u64 cliprects_ptr;
|
||||
#define I915_EXEC_RING_MASK (7<<0)
|
||||
#define I915_EXEC_DEFAULT (0<<0)
|
||||
#define I915_EXEC_RENDER (1<<0)
|
||||
#define I915_EXEC_BSD (2<<0)
|
||||
#define I915_EXEC_BLT (3<<0)
|
||||
|
||||
/* Used for switching the constants addressing mode on gen4+ RENDER ring.
|
||||
* Gen6+ only supports relative addressing to dynamic state (default) and
|
||||
* absolute addressing.
|
||||
*
|
||||
* These flags are ignored for the BSD and BLT rings.
|
||||
*/
|
||||
#define I915_EXEC_CONSTANTS_MASK (3<<6)
|
||||
#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */
|
||||
#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6)
|
||||
#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
|
||||
__u64 flags;
|
||||
__u64 rsvd1;
|
||||
__u64 rsvd2;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_pin {
|
||||
/** Handle of the buffer to be pinned. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
|
||||
/** alignment required within the aperture */
|
||||
__u64 alignment;
|
||||
|
||||
/** Returned GTT offset of the buffer. */
|
||||
__u64 offset;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_unpin {
|
||||
/** Handle of the buffer to be unpinned. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_busy {
|
||||
/** Handle of the buffer to check for busy */
|
||||
__u32 handle;
|
||||
|
||||
/** Return busy status (1 if busy, 0 if idle) */
|
||||
__u32 busy;
|
||||
};
|
||||
|
||||
#define I915_TILING_NONE 0
|
||||
#define I915_TILING_X 1
|
||||
#define I915_TILING_Y 2
|
||||
|
||||
#define I915_BIT_6_SWIZZLE_NONE 0
|
||||
#define I915_BIT_6_SWIZZLE_9 1
|
||||
#define I915_BIT_6_SWIZZLE_9_10 2
|
||||
#define I915_BIT_6_SWIZZLE_9_11 3
|
||||
#define I915_BIT_6_SWIZZLE_9_10_11 4
|
||||
/* Not seen by userland */
|
||||
#define I915_BIT_6_SWIZZLE_UNKNOWN 5
|
||||
/* Seen by userland. */
|
||||
#define I915_BIT_6_SWIZZLE_9_17 6
|
||||
#define I915_BIT_6_SWIZZLE_9_10_17 7
|
||||
|
||||
struct drm_i915_gem_set_tiling {
|
||||
/** Handle of the buffer to have its tiling state updated */
|
||||
__u32 handle;
|
||||
|
||||
/**
|
||||
* Tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
|
||||
* I915_TILING_Y).
|
||||
*
|
||||
* This value is to be set on request, and will be updated by the
|
||||
* kernel on successful return with the actual chosen tiling layout.
|
||||
*
|
||||
* The tiling mode may be demoted to I915_TILING_NONE when the system
|
||||
* has bit 6 swizzling that can't be managed correctly by GEM.
|
||||
*
|
||||
* Buffer contents become undefined when changing tiling_mode.
|
||||
*/
|
||||
__u32 tiling_mode;
|
||||
|
||||
/**
|
||||
* Stride in bytes for the object when in I915_TILING_X or
|
||||
* I915_TILING_Y.
|
||||
*/
|
||||
__u32 stride;
|
||||
|
||||
/**
|
||||
* Returned address bit 6 swizzling required for CPU access through
|
||||
* mmap mapping.
|
||||
*/
|
||||
__u32 swizzle_mode;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_get_tiling {
|
||||
/** Handle of the buffer to get tiling state for. */
|
||||
__u32 handle;
|
||||
|
||||
/**
|
||||
* Current tiling mode for the object (I915_TILING_NONE, I915_TILING_X,
|
||||
* I915_TILING_Y).
|
||||
*/
|
||||
__u32 tiling_mode;
|
||||
|
||||
/**
|
||||
* Returned address bit 6 swizzling required for CPU access through
|
||||
* mmap mapping.
|
||||
*/
|
||||
__u32 swizzle_mode;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_get_aperture {
|
||||
/** Total size of the aperture used by i915_gem_execbuffer, in bytes */
|
||||
__u64 aper_size;
|
||||
|
||||
/**
|
||||
* Available space in the aperture used by i915_gem_execbuffer, in
|
||||
* bytes
|
||||
*/
|
||||
__u64 aper_available_size;
|
||||
};
|
||||
|
||||
struct drm_i915_get_pipe_from_crtc_id {
|
||||
/** ID of CRTC being requested **/
|
||||
__u32 crtc_id;
|
||||
|
||||
/** pipe of requested CRTC **/
|
||||
__u32 pipe;
|
||||
};
|
||||
|
||||
#define I915_MADV_WILLNEED 0
|
||||
#define I915_MADV_DONTNEED 1
|
||||
#define __I915_MADV_PURGED 2 /* internal state */
|
||||
|
||||
struct drm_i915_gem_madvise {
|
||||
/** Handle of the buffer to change the backing store advice */
|
||||
__u32 handle;
|
||||
|
||||
/* Advice: either the buffer will be needed again in the near future,
|
||||
* or wont be and could be discarded under memory pressure.
|
||||
*/
|
||||
__u32 madv;
|
||||
|
||||
/** Whether the backing store still exists. */
|
||||
__u32 retained;
|
||||
};
|
||||
|
||||
/* flags */
|
||||
#define I915_OVERLAY_TYPE_MASK 0xff
|
||||
#define I915_OVERLAY_YUV_PLANAR 0x01
|
||||
#define I915_OVERLAY_YUV_PACKED 0x02
|
||||
#define I915_OVERLAY_RGB 0x03
|
||||
|
||||
#define I915_OVERLAY_DEPTH_MASK 0xff00
|
||||
#define I915_OVERLAY_RGB24 0x1000
|
||||
#define I915_OVERLAY_RGB16 0x2000
|
||||
#define I915_OVERLAY_RGB15 0x3000
|
||||
#define I915_OVERLAY_YUV422 0x0100
|
||||
#define I915_OVERLAY_YUV411 0x0200
|
||||
#define I915_OVERLAY_YUV420 0x0300
|
||||
#define I915_OVERLAY_YUV410 0x0400
|
||||
|
||||
#define I915_OVERLAY_SWAP_MASK 0xff0000
|
||||
#define I915_OVERLAY_NO_SWAP 0x000000
|
||||
#define I915_OVERLAY_UV_SWAP 0x010000
|
||||
#define I915_OVERLAY_Y_SWAP 0x020000
|
||||
#define I915_OVERLAY_Y_AND_UV_SWAP 0x030000
|
||||
|
||||
#define I915_OVERLAY_FLAGS_MASK 0xff000000
|
||||
#define I915_OVERLAY_ENABLE 0x01000000
|
||||
|
||||
struct drm_intel_overlay_put_image {
|
||||
/* various flags and src format description */
|
||||
__u32 flags;
|
||||
/* source picture description */
|
||||
__u32 bo_handle;
|
||||
/* stride values and offsets are in bytes, buffer relative */
|
||||
__u16 stride_Y; /* stride for packed formats */
|
||||
__u16 stride_UV;
|
||||
__u32 offset_Y; /* offset for packet formats */
|
||||
__u32 offset_U;
|
||||
__u32 offset_V;
|
||||
/* in pixels */
|
||||
__u16 src_width;
|
||||
__u16 src_height;
|
||||
/* to compensate the scaling factors for partially covered surfaces */
|
||||
__u16 src_scan_width;
|
||||
__u16 src_scan_height;
|
||||
/* output crtc description */
|
||||
__u32 crtc_id;
|
||||
__u16 dst_x;
|
||||
__u16 dst_y;
|
||||
__u16 dst_width;
|
||||
__u16 dst_height;
|
||||
};
|
||||
|
||||
/* flags */
|
||||
#define I915_OVERLAY_UPDATE_ATTRS (1<<0)
|
||||
#define I915_OVERLAY_UPDATE_GAMMA (1<<1)
|
||||
struct drm_intel_overlay_attrs {
|
||||
__u32 flags;
|
||||
__u32 color_key;
|
||||
__s32 brightness;
|
||||
__u32 contrast;
|
||||
__u32 saturation;
|
||||
__u32 gamma0;
|
||||
__u32 gamma1;
|
||||
__u32 gamma2;
|
||||
__u32 gamma3;
|
||||
__u32 gamma4;
|
||||
__u32 gamma5;
|
||||
};
|
||||
|
||||
#endif /* _I915_DRM_H_ */
|
@ -28,8 +28,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
//#include <linux/device.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -37,14 +42,24 @@
|
||||
#include <errno-base.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <syscall.h>
|
||||
|
||||
unsigned int i915_lvds_downclock = 0;
|
||||
int i915_vbt_sdvo_panel_type = -1;
|
||||
unsigned int i915_panel_use_ssc = 1;
|
||||
unsigned int i915_powersave = 1;
|
||||
unsigned int i915_enable_fbc = 1;
|
||||
#define __read_mostly
|
||||
|
||||
|
||||
int i915_panel_ignore_lid __read_mostly = 0;
|
||||
|
||||
unsigned int i915_powersave __read_mostly = 1;
|
||||
|
||||
unsigned int i915_enable_rc6 __read_mostly = 0;
|
||||
|
||||
unsigned int i915_enable_fbc __read_mostly = 1;
|
||||
|
||||
unsigned int i915_lvds_downclock __read_mostly = 0;
|
||||
|
||||
unsigned int i915_panel_use_ssc __read_mostly = 1;
|
||||
|
||||
int i915_vbt_sdvo_panel_type __read_mostly = -1;
|
||||
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
|
||||
@ -59,17 +74,14 @@ unsigned int i915_enable_fbc = 1;
|
||||
|
||||
static const struct intel_device_info intel_sandybridge_d_info = {
|
||||
.gen = 6,
|
||||
.need_gfx_hws = 1,
|
||||
.has_hotplug = 1,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.has_bsd_ring = 1,
|
||||
.has_blt_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_sandybridge_m_info = {
|
||||
.gen = 6,
|
||||
.is_mobile = 1,
|
||||
.need_gfx_hws = 1,
|
||||
.has_hotplug = 1,
|
||||
.gen = 6, .is_mobile = 1,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.has_fbc = 1,
|
||||
.has_bsd_ring = 1,
|
||||
.has_blt_ring = 1,
|
||||
@ -256,7 +268,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
mutex_init(&dev->struct_mutex);
|
||||
mutex_init(&dev->ctxlist_mutex);
|
||||
|
||||
//int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
|
||||
|
||||
ret = i915_driver_load(dev, ent->driver_data );
|
||||
// if (ret)
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "intel_bios.h"
|
||||
#include "intel_ringbuffer.h"
|
||||
//#include <linux/io-mapping.h>
|
||||
//#include <linux/i2c.h>
|
||||
#include <linux/i2c.h>
|
||||
//#include <drm/intel-gtt.h>
|
||||
//#include <linux/backlight.h>
|
||||
|
||||
@ -119,7 +119,10 @@ struct intel_opregion {
|
||||
struct intel_overlay;
|
||||
struct intel_overlay_error_state;
|
||||
|
||||
|
||||
struct drm_i915_master_private {
|
||||
drm_local_map_t *sarea;
|
||||
struct _drm_i915_sarea *sarea_priv;
|
||||
};
|
||||
#define I915_FENCE_REG_NONE -1
|
||||
|
||||
struct drm_i915_fence_reg {
|
||||
@ -323,7 +326,7 @@ typedef struct drm_i915_private {
|
||||
|
||||
/* For hangcheck timer */
|
||||
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
|
||||
// struct timer_list hangcheck_timer;
|
||||
struct timer_list hangcheck_timer;
|
||||
int hangcheck_count;
|
||||
uint32_t last_acthd;
|
||||
uint32_t last_instdone;
|
||||
@ -547,7 +550,7 @@ typedef struct drm_i915_private {
|
||||
/** Bridge to intel-gtt-ko */
|
||||
const struct intel_gtt *gtt;
|
||||
/** Memory allocator for GTT stolen memory */
|
||||
// struct drm_mm stolen;
|
||||
struct drm_mm stolen;
|
||||
/** Memory allocator for GTT */
|
||||
// struct drm_mm gtt_space;
|
||||
/** List of all objects in gtt_space. Used to restore gtt
|
||||
@ -681,7 +684,7 @@ typedef struct drm_i915_private {
|
||||
/* indicates the reduced downclock for LVDS*/
|
||||
int lvds_downclock;
|
||||
// struct work_struct idle_work;
|
||||
// struct timer_list idle_timer;
|
||||
struct timer_list idle_timer;
|
||||
bool busy;
|
||||
u16 orig_clock;
|
||||
int child_dev_num;
|
||||
@ -704,7 +707,7 @@ typedef struct drm_i915_private {
|
||||
u64 last_count1;
|
||||
unsigned long last_time1;
|
||||
u64 last_count2;
|
||||
// struct timespec last_time2;
|
||||
struct timespec last_time2;
|
||||
unsigned long gfx_power;
|
||||
int c_m;
|
||||
int r_t;
|
||||
|
@ -27,12 +27,12 @@
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
//#include "i915_drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
//#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
//#include <linux/shmem_fs.h>
|
||||
//#include <linux/slab.h>
|
||||
#include <linux/slab.h>
|
||||
//#include <linux/swap.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "linux/bitops.h"
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
//#include "i915_drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/** @file i915_gem_tiling.c
|
||||
|
@ -27,12 +27,10 @@
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
//#include "i915_drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_bios.h"
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
#define SLAVE_ADDR1 0x70
|
||||
#define SLAVE_ADDR2 0x72
|
||||
|
||||
|
609
drivers/video/drm/i915/intel_crt.c
Normal file
609
drivers/video/drm/i915/intel_crt.c
Normal file
@ -0,0 +1,609 @@
|
||||
/*
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "drm_edid.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/* Here's the desired hotplug mode */
|
||||
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
|
||||
ADPA_CRT_HOTPLUG_WARMUP_10MS | \
|
||||
ADPA_CRT_HOTPLUG_SAMPLE_4S | \
|
||||
ADPA_CRT_HOTPLUG_VOLTAGE_50 | \
|
||||
ADPA_CRT_HOTPLUG_VOLREF_325MV | \
|
||||
ADPA_CRT_HOTPLUG_ENABLE)
|
||||
|
||||
struct intel_crt {
|
||||
struct intel_encoder base;
|
||||
bool force_hotplug_required;
|
||||
};
|
||||
|
||||
static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_crt, base);
|
||||
}
|
||||
|
||||
static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 temp, reg;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
reg = PCH_ADPA;
|
||||
else
|
||||
reg = ADPA;
|
||||
|
||||
temp = I915_READ(reg);
|
||||
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
|
||||
temp &= ~ADPA_DAC_ENABLE;
|
||||
|
||||
switch(mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
temp |= ADPA_DAC_ENABLE;
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
I915_WRITE(reg, temp);
|
||||
}
|
||||
|
||||
static int intel_crt_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
int max_clock = 0;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
if (mode->clock < 25000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (IS_GEN2(dev))
|
||||
max_clock = 350000;
|
||||
else
|
||||
max_clock = 400000;
|
||||
if (mode->clock > max_clock)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static bool intel_crt_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_crt_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int dpll_md_reg;
|
||||
u32 adpa, dpll_md;
|
||||
u32 adpa_reg;
|
||||
|
||||
dpll_md_reg = DPLL_MD(intel_crtc->pipe);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
adpa_reg = PCH_ADPA;
|
||||
else
|
||||
adpa_reg = ADPA;
|
||||
|
||||
/*
|
||||
* Disable separate mode multiplier used when cloning SDVO to CRT
|
||||
* XXX this needs to be adjusted when we really are cloning
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
|
||||
dpll_md = I915_READ(dpll_md_reg);
|
||||
I915_WRITE(dpll_md_reg,
|
||||
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
||||
}
|
||||
|
||||
adpa = ADPA_HOTPLUG_BITS;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
adpa |= ADPA_HSYNC_ACTIVE_HIGH;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (intel_crtc->pipe == 0) {
|
||||
if (HAS_PCH_CPT(dev))
|
||||
adpa |= PORT_TRANS_A_SEL_CPT;
|
||||
else
|
||||
adpa |= ADPA_PIPE_A_SELECT;
|
||||
} else {
|
||||
if (HAS_PCH_CPT(dev))
|
||||
adpa |= PORT_TRANS_B_SEL_CPT;
|
||||
else
|
||||
adpa |= ADPA_PIPE_B_SELECT;
|
||||
}
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
|
||||
|
||||
I915_WRITE(adpa_reg, adpa);
|
||||
}
|
||||
|
||||
static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct intel_crt *crt = intel_attached_crt(connector);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 adpa;
|
||||
bool ret;
|
||||
|
||||
/* The first time through, trigger an explicit detection cycle */
|
||||
if (crt->force_hotplug_required) {
|
||||
bool turn_off_dac = HAS_PCH_SPLIT(dev);
|
||||
u32 save_adpa;
|
||||
|
||||
crt->force_hotplug_required = 0;
|
||||
|
||||
save_adpa = adpa = I915_READ(PCH_ADPA);
|
||||
DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
|
||||
|
||||
adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
|
||||
if (turn_off_dac)
|
||||
adpa &= ~ADPA_DAC_ENABLE;
|
||||
|
||||
I915_WRITE(PCH_ADPA, adpa);
|
||||
|
||||
if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
|
||||
1000))
|
||||
DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
|
||||
|
||||
if (turn_off_dac) {
|
||||
I915_WRITE(PCH_ADPA, save_adpa);
|
||||
POSTING_READ(PCH_ADPA);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the status to see if both blue and green are on now */
|
||||
adpa = I915_READ(PCH_ADPA);
|
||||
if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
|
||||
ret = true;
|
||||
else
|
||||
ret = false;
|
||||
DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
|
||||
*
|
||||
* Not for i915G/i915GM
|
||||
*
|
||||
* \return true if CRT is connected.
|
||||
* \return false if CRT is disconnected.
|
||||
*/
|
||||
static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 hotplug_en, orig, stat;
|
||||
bool ret = false;
|
||||
int i, tries = 0;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return intel_ironlake_crt_detect_hotplug(connector);
|
||||
|
||||
/*
|
||||
* On 4 series desktop, CRT detect sequence need to be done twice
|
||||
* to get a reliable result.
|
||||
*/
|
||||
|
||||
if (IS_G4X(dev) && !IS_GM45(dev))
|
||||
tries = 2;
|
||||
else
|
||||
tries = 1;
|
||||
hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN);
|
||||
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
|
||||
|
||||
for (i = 0; i < tries ; i++) {
|
||||
/* turn on the FORCE_DETECT */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
/* wait for FORCE_DETECT to go off */
|
||||
if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
|
||||
CRT_HOTPLUG_FORCE_DETECT) == 0,
|
||||
1000))
|
||||
DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off");
|
||||
}
|
||||
|
||||
stat = I915_READ(PORT_HOTPLUG_STAT);
|
||||
if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
|
||||
ret = true;
|
||||
|
||||
/* clear the interrupt we just generated, if any */
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
|
||||
|
||||
/* and put the bits back */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, orig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool intel_crt_detect_ddc(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_crt *crt = intel_attached_crt(connector);
|
||||
struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
|
||||
|
||||
/* CRT should always be at 0, but check anyway */
|
||||
if (crt->base.type != INTEL_OUTPUT_ANALOG)
|
||||
return false;
|
||||
|
||||
if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
|
||||
struct edid *edid;
|
||||
bool is_digital = false;
|
||||
|
||||
edid = drm_get_edid(connector,
|
||||
&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
|
||||
/*
|
||||
* This may be a DVI-I connector with a shared DDC
|
||||
* link between analog and digital outputs, so we
|
||||
* have to check the EDID input spec of the attached device.
|
||||
*
|
||||
* On the other hand, what should we do if it is a broken EDID?
|
||||
*/
|
||||
if (edid != NULL) {
|
||||
is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
|
||||
connector->display_info.raw_edid = NULL;
|
||||
kfree(edid);
|
||||
}
|
||||
|
||||
if (!is_digital) {
|
||||
DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
|
||||
return true;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_crt_load_detect(struct intel_crt *crt)
|
||||
{
|
||||
struct drm_device *dev = crt->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t pipe = to_intel_crtc(crt->base.base.crtc)->pipe;
|
||||
uint32_t save_bclrpat;
|
||||
uint32_t save_vtotal;
|
||||
uint32_t vtotal, vactive;
|
||||
uint32_t vsample;
|
||||
uint32_t vblank, vblank_start, vblank_end;
|
||||
uint32_t dsl;
|
||||
uint32_t bclrpat_reg;
|
||||
uint32_t vtotal_reg;
|
||||
uint32_t vblank_reg;
|
||||
uint32_t vsync_reg;
|
||||
uint32_t pipeconf_reg;
|
||||
uint32_t pipe_dsl_reg;
|
||||
uint8_t st00;
|
||||
enum drm_connector_status status;
|
||||
|
||||
DRM_DEBUG_KMS("starting load-detect on CRT\n");
|
||||
|
||||
bclrpat_reg = BCLRPAT(pipe);
|
||||
vtotal_reg = VTOTAL(pipe);
|
||||
vblank_reg = VBLANK(pipe);
|
||||
vsync_reg = VSYNC(pipe);
|
||||
pipeconf_reg = PIPECONF(pipe);
|
||||
pipe_dsl_reg = PIPEDSL(pipe);
|
||||
|
||||
save_bclrpat = I915_READ(bclrpat_reg);
|
||||
save_vtotal = I915_READ(vtotal_reg);
|
||||
vblank = I915_READ(vblank_reg);
|
||||
|
||||
vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
|
||||
vactive = (save_vtotal & 0x7ff) + 1;
|
||||
|
||||
vblank_start = (vblank & 0xfff) + 1;
|
||||
vblank_end = ((vblank >> 16) & 0xfff) + 1;
|
||||
|
||||
/* Set the border color to purple. */
|
||||
I915_WRITE(bclrpat_reg, 0x500050);
|
||||
|
||||
if (!IS_GEN2(dev)) {
|
||||
uint32_t pipeconf = I915_READ(pipeconf_reg);
|
||||
I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
|
||||
POSTING_READ(pipeconf_reg);
|
||||
/* Wait for next Vblank to substitue
|
||||
* border color for Color info */
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
st00 = I915_READ8(VGA_MSR_WRITE);
|
||||
status = ((st00 & (1 << 4)) != 0) ?
|
||||
connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
|
||||
I915_WRITE(pipeconf_reg, pipeconf);
|
||||
} else {
|
||||
bool restore_vblank = false;
|
||||
int count, detect;
|
||||
|
||||
/*
|
||||
* If there isn't any border, add some.
|
||||
* Yes, this will flicker
|
||||
*/
|
||||
if (vblank_start <= vactive && vblank_end >= vtotal) {
|
||||
uint32_t vsync = I915_READ(vsync_reg);
|
||||
uint32_t vsync_start = (vsync & 0xffff) + 1;
|
||||
|
||||
vblank_start = vsync_start;
|
||||
I915_WRITE(vblank_reg,
|
||||
(vblank_start - 1) |
|
||||
((vblank_end - 1) << 16));
|
||||
restore_vblank = true;
|
||||
}
|
||||
/* sample in the vertical border, selecting the larger one */
|
||||
if (vblank_start - vactive >= vtotal - vblank_end)
|
||||
vsample = (vblank_start + vactive) >> 1;
|
||||
else
|
||||
vsample = (vtotal + vblank_end) >> 1;
|
||||
|
||||
/*
|
||||
* Wait for the border to be displayed
|
||||
*/
|
||||
while (I915_READ(pipe_dsl_reg) >= vactive)
|
||||
;
|
||||
while ((dsl = I915_READ(pipe_dsl_reg)) <= vsample)
|
||||
;
|
||||
/*
|
||||
* Watch ST00 for an entire scanline
|
||||
*/
|
||||
detect = 0;
|
||||
count = 0;
|
||||
do {
|
||||
count++;
|
||||
/* Read the ST00 VGA status register */
|
||||
st00 = I915_READ8(VGA_MSR_WRITE);
|
||||
if (st00 & (1 << 4))
|
||||
detect++;
|
||||
} while ((I915_READ(pipe_dsl_reg) == dsl));
|
||||
|
||||
/* restore vblank if necessary */
|
||||
if (restore_vblank)
|
||||
I915_WRITE(vblank_reg, vblank);
|
||||
/*
|
||||
* If more than 3/4 of the scanline detected a monitor,
|
||||
* then it is assumed to be present. This works even on i830,
|
||||
* where there isn't any way to force the border color across
|
||||
* the screen
|
||||
*/
|
||||
status = detect * 4 > count * 3 ?
|
||||
connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
}
|
||||
|
||||
/* Restore previous settings */
|
||||
I915_WRITE(bclrpat_reg, save_bclrpat);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_crt_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct intel_crt *crt = intel_attached_crt(connector);
|
||||
struct drm_crtc *crtc;
|
||||
enum drm_connector_status status;
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev)) {
|
||||
if (intel_crt_detect_hotplug(connector)) {
|
||||
DRM_DEBUG_KMS("CRT detected via hotplug\n");
|
||||
return connector_status_connected;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("CRT not detected via hotplug\n");
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
}
|
||||
|
||||
if (intel_crt_detect_ddc(connector))
|
||||
return connector_status_connected;
|
||||
|
||||
if (!force)
|
||||
return connector->status;
|
||||
|
||||
/* for pre-945g platforms use load detect */
|
||||
crtc = crt->base.base.crtc;
|
||||
if (crtc && crtc->enabled) {
|
||||
status = intel_crt_load_detect(crt);
|
||||
} else {
|
||||
struct intel_load_detect_pipe tmp;
|
||||
|
||||
if (intel_get_load_detect_pipe(&crt->base, connector, NULL,
|
||||
&tmp)) {
|
||||
if (intel_crt_detect_ddc(connector))
|
||||
status = connector_status_connected;
|
||||
else
|
||||
status = intel_crt_load_detect(crt);
|
||||
intel_release_load_detect_pipe(&crt->base, connector,
|
||||
&tmp);
|
||||
} else
|
||||
status = connector_status_unknown;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void intel_crt_destroy(struct drm_connector *connector)
|
||||
{
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static int intel_crt_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
|
||||
if (ret || !IS_G4X(dev))
|
||||
return ret;
|
||||
|
||||
/* Try to probe digital port for output in DVI-I -> VGA mode. */
|
||||
return intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[GMBUS_PORT_DPB].adapter);
|
||||
}
|
||||
|
||||
static int intel_crt_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_crt_reset(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct intel_crt *crt = intel_attached_crt(connector);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
crt->force_hotplug_required = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines for controlling stuff on the analog port
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = {
|
||||
.dpms = intel_crt_dpms,
|
||||
.mode_fixup = intel_crt_mode_fixup,
|
||||
.prepare = intel_encoder_prepare,
|
||||
.commit = intel_encoder_commit,
|
||||
.mode_set = intel_crt_mode_set,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_crt_connector_funcs = {
|
||||
.reset = intel_crt_reset,
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = intel_crt_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = intel_crt_destroy,
|
||||
.set_property = intel_crt_set_property,
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
|
||||
.mode_valid = intel_crt_mode_valid,
|
||||
.get_modes = intel_crt_get_modes,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
||||
.destroy = intel_encoder_destroy,
|
||||
};
|
||||
|
||||
void intel_crt_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct intel_crt *crt;
|
||||
struct intel_connector *intel_connector;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
|
||||
if (!crt)
|
||||
return;
|
||||
|
||||
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
||||
if (!intel_connector) {
|
||||
kfree(crt);
|
||||
return;
|
||||
}
|
||||
|
||||
connector = &intel_connector->base;
|
||||
drm_connector_init(dev, &intel_connector->base,
|
||||
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
|
||||
|
||||
drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
|
||||
DRM_MODE_ENCODER_DAC);
|
||||
|
||||
intel_connector_attach_encoder(intel_connector, &crt->base);
|
||||
|
||||
crt->base.type = INTEL_OUTPUT_ANALOG;
|
||||
crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
|
||||
1 << INTEL_ANALOG_CLONE_BIT |
|
||||
1 << INTEL_SDVO_LVDS_CLONE_BIT);
|
||||
crt->base.crtc_mask = (1 << 0) | (1 << 1);
|
||||
connector->interlace_allowed = 1;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs);
|
||||
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
|
||||
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
if (I915_HAS_HOTPLUG(dev))
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
/*
|
||||
* Configure the automatic hotplug detection stuff
|
||||
*/
|
||||
crt->force_hotplug_required = 0;
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
u32 adpa;
|
||||
|
||||
adpa = I915_READ(PCH_ADPA);
|
||||
adpa &= ~ADPA_CRT_HOTPLUG_MASK;
|
||||
adpa |= ADPA_HOTPLUG_BITS;
|
||||
I915_WRITE(PCH_ADPA, adpa);
|
||||
POSTING_READ(PCH_ADPA);
|
||||
|
||||
DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa);
|
||||
crt->force_hotplug_required = 1;
|
||||
}
|
||||
|
||||
dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,7 @@
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include "drm_fb_helper.h"
|
||||
#include <syscall.h>
|
||||
|
||||
#define _wait_for(COND, MS, W) ({ \
|
||||
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
|
||||
@ -39,7 +40,7 @@
|
||||
ret__ = -ETIMEDOUT; \
|
||||
break; \
|
||||
} \
|
||||
if (W && !(/*in_atomic()||*/ in_dbg_master())) msleep(W); \
|
||||
if (W) msleep(W); \
|
||||
} \
|
||||
ret__; \
|
||||
})
|
||||
|
448
drivers/video/drm/i915/intel_dvo.c
Normal file
448
drivers/video/drm/i915/intel_dvo.c
Normal file
@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "dvo.h"
|
||||
|
||||
#define SIL164_ADDR 0x38
|
||||
#define CH7xxx_ADDR 0x76
|
||||
#define TFP410_ADDR 0x38
|
||||
|
||||
static const struct intel_dvo_device intel_dvo_devices[] = {
|
||||
{
|
||||
.type = INTEL_DVO_CHIP_TMDS,
|
||||
.name = "sil164",
|
||||
.dvo_reg = DVOC,
|
||||
.slave_addr = SIL164_ADDR,
|
||||
.dev_ops = &sil164_ops,
|
||||
},
|
||||
{
|
||||
.type = INTEL_DVO_CHIP_TMDS,
|
||||
.name = "ch7xxx",
|
||||
.dvo_reg = DVOC,
|
||||
.slave_addr = CH7xxx_ADDR,
|
||||
.dev_ops = &ch7xxx_ops,
|
||||
},
|
||||
{
|
||||
.type = INTEL_DVO_CHIP_LVDS,
|
||||
.name = "ivch",
|
||||
.dvo_reg = DVOA,
|
||||
.slave_addr = 0x02, /* Might also be 0x44, 0x84, 0xc4 */
|
||||
.dev_ops = &ivch_ops,
|
||||
},
|
||||
{
|
||||
.type = INTEL_DVO_CHIP_TMDS,
|
||||
.name = "tfp410",
|
||||
.dvo_reg = DVOC,
|
||||
.slave_addr = TFP410_ADDR,
|
||||
.dev_ops = &tfp410_ops,
|
||||
},
|
||||
{
|
||||
.type = INTEL_DVO_CHIP_LVDS,
|
||||
.name = "ch7017",
|
||||
.dvo_reg = DVOC,
|
||||
.slave_addr = 0x75,
|
||||
.gpio = GMBUS_PORT_DPB,
|
||||
.dev_ops = &ch7017_ops,
|
||||
}
|
||||
};
|
||||
|
||||
struct intel_dvo {
|
||||
struct intel_encoder base;
|
||||
|
||||
struct intel_dvo_device dev;
|
||||
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
bool panel_wants_dither;
|
||||
};
|
||||
|
||||
static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(encoder, struct intel_dvo, base.base);
|
||||
}
|
||||
|
||||
static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_dvo, base);
|
||||
}
|
||||
|
||||
static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
u32 dvo_reg = intel_dvo->dev.dvo_reg;
|
||||
u32 temp = I915_READ(dvo_reg);
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON) {
|
||||
I915_WRITE(dvo_reg, temp | DVO_ENABLE);
|
||||
I915_READ(dvo_reg);
|
||||
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
|
||||
} else {
|
||||
intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
|
||||
I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
|
||||
I915_READ(dvo_reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_dvo_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
/* XXX: Validate clock range */
|
||||
|
||||
if (intel_dvo->panel_fixed_mode) {
|
||||
if (mode->hdisplay > intel_dvo->panel_fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
if (mode->vdisplay > intel_dvo->panel_fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
}
|
||||
|
||||
return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
|
||||
}
|
||||
|
||||
static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
|
||||
/* If we have timings from the BIOS for the panel, put them in
|
||||
* to the adjusted mode. The CRTC will be set up for this mode,
|
||||
* with the panel scaling set up to source from the H/VDisplay
|
||||
* of the original mode.
|
||||
*/
|
||||
if (intel_dvo->panel_fixed_mode != NULL) {
|
||||
#define C(x) adjusted_mode->x = intel_dvo->panel_fixed_mode->x
|
||||
C(hdisplay);
|
||||
C(hsync_start);
|
||||
C(hsync_end);
|
||||
C(htotal);
|
||||
C(vdisplay);
|
||||
C(vsync_start);
|
||||
C(vsync_end);
|
||||
C(vtotal);
|
||||
C(clock);
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
#undef C
|
||||
}
|
||||
|
||||
if (intel_dvo->dev.dev_ops->mode_fixup)
|
||||
return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev, mode, adjusted_mode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void intel_dvo_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
int pipe = intel_crtc->pipe;
|
||||
u32 dvo_val;
|
||||
u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
|
||||
int dpll_reg = DPLL(pipe);
|
||||
|
||||
switch (dvo_reg) {
|
||||
case DVOA:
|
||||
default:
|
||||
dvo_srcdim_reg = DVOA_SRCDIM;
|
||||
break;
|
||||
case DVOB:
|
||||
dvo_srcdim_reg = DVOB_SRCDIM;
|
||||
break;
|
||||
case DVOC:
|
||||
dvo_srcdim_reg = DVOC_SRCDIM;
|
||||
break;
|
||||
}
|
||||
|
||||
intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, mode, adjusted_mode);
|
||||
|
||||
/* Save the data order, since I don't know what it should be set to. */
|
||||
dvo_val = I915_READ(dvo_reg) &
|
||||
(DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
|
||||
dvo_val |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE |
|
||||
DVO_BLANK_ACTIVE_HIGH;
|
||||
|
||||
if (pipe == 1)
|
||||
dvo_val |= DVO_PIPE_B_SELECT;
|
||||
dvo_val |= DVO_PIPE_STALL;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
dvo_val |= DVO_HSYNC_ACTIVE_HIGH;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
dvo_val |= DVO_VSYNC_ACTIVE_HIGH;
|
||||
|
||||
I915_WRITE(dpll_reg, I915_READ(dpll_reg) | DPLL_DVO_HIGH_SPEED);
|
||||
|
||||
/*I915_WRITE(DVOB_SRCDIM,
|
||||
(adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(adjusted_mode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));*/
|
||||
I915_WRITE(dvo_srcdim_reg,
|
||||
(adjusted_mode->hdisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
|
||||
(adjusted_mode->vdisplay << DVO_SRCDIM_VERTICAL_SHIFT));
|
||||
/*I915_WRITE(DVOB, dvo_val);*/
|
||||
I915_WRITE(dvo_reg, dvo_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the output connection on our DVO device.
|
||||
*
|
||||
* Unimplemented.
|
||||
*/
|
||||
static enum drm_connector_status
|
||||
intel_dvo_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
|
||||
}
|
||||
|
||||
static int intel_dvo_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
|
||||
/* We should probably have an i2c driver get_modes function for those
|
||||
* devices which will have a fixed set of modes determined by the chip
|
||||
* (TV-out, for example), but for now with just TMDS and LVDS,
|
||||
* that's not the case.
|
||||
*/
|
||||
intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[GMBUS_PORT_DPC].adapter);
|
||||
if (!list_empty(&connector->probed_modes))
|
||||
return 1;
|
||||
|
||||
if (intel_dvo->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode;
|
||||
mode = drm_mode_duplicate(connector->dev, intel_dvo->panel_fixed_mode);
|
||||
if (mode) {
|
||||
drm_mode_probed_add(connector, mode);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_dvo_destroy(struct drm_connector *connector)
|
||||
{
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
|
||||
.dpms = intel_dvo_dpms,
|
||||
.mode_fixup = intel_dvo_mode_fixup,
|
||||
.prepare = intel_encoder_prepare,
|
||||
.mode_set = intel_dvo_mode_set,
|
||||
.commit = intel_encoder_commit,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = intel_dvo_detect,
|
||||
.destroy = intel_dvo_destroy,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
|
||||
.mode_valid = intel_dvo_mode_valid,
|
||||
.get_modes = intel_dvo_get_modes,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
|
||||
{
|
||||
struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
|
||||
|
||||
if (intel_dvo->dev.dev_ops->destroy)
|
||||
intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev);
|
||||
|
||||
kfree(intel_dvo->panel_fixed_mode);
|
||||
|
||||
intel_encoder_destroy(encoder);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
|
||||
.destroy = intel_dvo_enc_destroy,
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to get a fixed panel timing for LVDS (currently only the i830).
|
||||
*
|
||||
* Other chips with DVO LVDS will need to extend this to deal with the LVDS
|
||||
* chip being on DVOB/C and having multiple pipes.
|
||||
*/
|
||||
static struct drm_display_mode *
|
||||
intel_dvo_get_current_mode(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
|
||||
uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg);
|
||||
struct drm_display_mode *mode = NULL;
|
||||
|
||||
/* If the DVO port is active, that'll be the LVDS, so we can pull out
|
||||
* its timings to get how the BIOS set up the panel.
|
||||
*/
|
||||
if (dvo_val & DVO_ENABLE) {
|
||||
struct drm_crtc *crtc;
|
||||
int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0;
|
||||
|
||||
crtc = intel_get_crtc_for_pipe(dev, pipe);
|
||||
if (crtc) {
|
||||
mode = intel_crtc_mode_get(dev, crtc);
|
||||
if (mode) {
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
if (dvo_val & DVO_HSYNC_ACTIVE_HIGH)
|
||||
mode->flags |= DRM_MODE_FLAG_PHSYNC;
|
||||
if (dvo_val & DVO_VSYNC_ACTIVE_HIGH)
|
||||
mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
void intel_dvo_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_dvo *intel_dvo;
|
||||
struct intel_connector *intel_connector;
|
||||
int i;
|
||||
int encoder_type = DRM_MODE_ENCODER_NONE;
|
||||
|
||||
intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL);
|
||||
if (!intel_dvo)
|
||||
return;
|
||||
|
||||
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
||||
if (!intel_connector) {
|
||||
kfree(intel_dvo);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_encoder = &intel_dvo->base;
|
||||
drm_encoder_init(dev, &intel_encoder->base,
|
||||
&intel_dvo_enc_funcs, encoder_type);
|
||||
|
||||
/* Now, try to find a controller */
|
||||
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
|
||||
struct drm_connector *connector = &intel_connector->base;
|
||||
const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
|
||||
struct i2c_adapter *i2c;
|
||||
int gpio;
|
||||
|
||||
/* Allow the I2C driver info to specify the GPIO to be used in
|
||||
* special cases, but otherwise default to what's defined
|
||||
* in the spec.
|
||||
*/
|
||||
if (dvo->gpio != 0)
|
||||
gpio = dvo->gpio;
|
||||
else if (dvo->type == INTEL_DVO_CHIP_LVDS)
|
||||
gpio = GMBUS_PORT_SSC;
|
||||
else
|
||||
gpio = GMBUS_PORT_DPB;
|
||||
|
||||
/* Set up the I2C bus necessary for the chip we're probing.
|
||||
* It appears that everything is on GPIOE except for panels
|
||||
* on i830 laptops, which are on GPIOB (DVOA).
|
||||
*/
|
||||
i2c = &dev_priv->gmbus[gpio].adapter;
|
||||
|
||||
intel_dvo->dev = *dvo;
|
||||
if (!dvo->dev_ops->init(&intel_dvo->dev, i2c))
|
||||
continue;
|
||||
|
||||
intel_encoder->type = INTEL_OUTPUT_DVO;
|
||||
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
||||
switch (dvo->type) {
|
||||
case INTEL_DVO_CHIP_TMDS:
|
||||
intel_encoder->clone_mask =
|
||||
(1 << INTEL_DVO_TMDS_CLONE_BIT) |
|
||||
(1 << INTEL_ANALOG_CLONE_BIT);
|
||||
drm_connector_init(dev, connector,
|
||||
&intel_dvo_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DVII);
|
||||
encoder_type = DRM_MODE_ENCODER_TMDS;
|
||||
break;
|
||||
case INTEL_DVO_CHIP_LVDS:
|
||||
intel_encoder->clone_mask =
|
||||
(1 << INTEL_DVO_LVDS_CLONE_BIT);
|
||||
drm_connector_init(dev, connector,
|
||||
&intel_dvo_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_LVDS);
|
||||
encoder_type = DRM_MODE_ENCODER_LVDS;
|
||||
break;
|
||||
}
|
||||
|
||||
drm_connector_helper_add(connector,
|
||||
&intel_dvo_connector_helper_funcs);
|
||||
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
|
||||
connector->interlace_allowed = false;
|
||||
connector->doublescan_allowed = false;
|
||||
|
||||
drm_encoder_helper_add(&intel_encoder->base,
|
||||
&intel_dvo_helper_funcs);
|
||||
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
if (dvo->type == INTEL_DVO_CHIP_LVDS) {
|
||||
/* For our LVDS chipsets, we should hopefully be able
|
||||
* to dig the fixed panel mode out of the BIOS data.
|
||||
* However, it's in a different format from the BIOS
|
||||
* data on chipsets with integrated LVDS (stored in AIM
|
||||
* headers, likely), so for now, just get the current
|
||||
* mode being output through DVO.
|
||||
*/
|
||||
intel_dvo->panel_fixed_mode =
|
||||
intel_dvo_get_current_mode(connector);
|
||||
intel_dvo->panel_wants_dither = true;
|
||||
}
|
||||
|
||||
drm_sysfs_connector_add(connector);
|
||||
return;
|
||||
}
|
||||
|
||||
drm_encoder_cleanup(&intel_encoder->base);
|
||||
kfree(intel_dvo);
|
||||
kfree(intel_connector);
|
||||
}
|
561
drivers/video/drm/i915/intel_hdmi.c
Normal file
561
drivers/video/drm/i915/intel_hdmi.c
Normal file
@ -0,0 +1,561 @@
|
||||
/*
|
||||
* Copyright 2006 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright © 2006-2009 Intel Corporation
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
//#include <linux/delay.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_edid.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
struct intel_hdmi {
|
||||
struct intel_encoder base;
|
||||
u32 sdvox_reg;
|
||||
int ddc_bus;
|
||||
uint32_t color_range;
|
||||
bool has_hdmi_sink;
|
||||
bool has_audio;
|
||||
int force_audio;
|
||||
void (*write_infoframe)(struct drm_encoder *encoder,
|
||||
struct dip_infoframe *frame);
|
||||
};
|
||||
|
||||
static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
|
||||
{
|
||||
return container_of(encoder, struct intel_hdmi, base.base);
|
||||
}
|
||||
|
||||
static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector)
|
||||
{
|
||||
return container_of(intel_attached_encoder(connector),
|
||||
struct intel_hdmi, base);
|
||||
}
|
||||
|
||||
void intel_dip_infoframe_csum(struct dip_infoframe *frame)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)frame;
|
||||
uint8_t sum = 0;
|
||||
unsigned i;
|
||||
|
||||
frame->checksum = 0;
|
||||
frame->ecc = 0;
|
||||
|
||||
/* Header isn't part of the checksum */
|
||||
for (i = 5; i < frame->len; i++)
|
||||
sum += data[i];
|
||||
|
||||
frame->checksum = 0x100 - sum;
|
||||
}
|
||||
|
||||
static u32 intel_infoframe_index(struct dip_infoframe *frame)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
switch (frame->type) {
|
||||
case DIP_TYPE_AVI:
|
||||
flags |= VIDEO_DIP_SELECT_AVI;
|
||||
break;
|
||||
case DIP_TYPE_SPD:
|
||||
flags |= VIDEO_DIP_SELECT_SPD;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static u32 intel_infoframe_flags(struct dip_infoframe *frame)
|
||||
{
|
||||
u32 flags = 0;
|
||||
|
||||
switch (frame->type) {
|
||||
case DIP_TYPE_AVI:
|
||||
flags |= VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_FREQ_VSYNC;
|
||||
break;
|
||||
case DIP_TYPE_SPD:
|
||||
flags |= VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_FREQ_2VSYNC;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("unknown info frame type %d\n", frame->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void i9xx_write_infoframe(struct drm_encoder *encoder,
|
||||
struct dip_infoframe *frame)
|
||||
{
|
||||
uint32_t *data = (uint32_t *)frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
u32 port, flags, val = I915_READ(VIDEO_DIP_CTL);
|
||||
unsigned i, len = DIP_HEADER_SIZE + frame->len;
|
||||
|
||||
|
||||
/* XXX first guess at handling video port, is this corrent? */
|
||||
if (intel_hdmi->sdvox_reg == SDVOB)
|
||||
port = VIDEO_DIP_PORT_B;
|
||||
else if (intel_hdmi->sdvox_reg == SDVOC)
|
||||
port = VIDEO_DIP_PORT_C;
|
||||
else
|
||||
return;
|
||||
|
||||
flags = intel_infoframe_index(frame);
|
||||
|
||||
val &= ~VIDEO_DIP_SELECT_MASK;
|
||||
|
||||
I915_WRITE(VIDEO_DIP_CTL, val | port | flags);
|
||||
|
||||
for (i = 0; i < len; i += 4) {
|
||||
I915_WRITE(VIDEO_DIP_DATA, *data);
|
||||
data++;
|
||||
}
|
||||
|
||||
flags |= intel_infoframe_flags(frame);
|
||||
|
||||
I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags);
|
||||
}
|
||||
|
||||
static void ironlake_write_infoframe(struct drm_encoder *encoder,
|
||||
struct dip_infoframe *frame)
|
||||
{
|
||||
uint32_t *data = (uint32_t *)frame;
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
int reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
|
||||
unsigned i, len = DIP_HEADER_SIZE + frame->len;
|
||||
u32 flags, val = I915_READ(reg);
|
||||
|
||||
intel_wait_for_vblank(dev, intel_crtc->pipe);
|
||||
|
||||
flags = intel_infoframe_index(frame);
|
||||
|
||||
val &= ~VIDEO_DIP_SELECT_MASK;
|
||||
|
||||
I915_WRITE(reg, val | flags);
|
||||
|
||||
for (i = 0; i < len; i += 4) {
|
||||
I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data);
|
||||
data++;
|
||||
}
|
||||
|
||||
flags |= intel_infoframe_flags(frame);
|
||||
|
||||
I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);
|
||||
}
|
||||
static void intel_set_infoframe(struct drm_encoder *encoder,
|
||||
struct dip_infoframe *frame)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
|
||||
if (!intel_hdmi->has_hdmi_sink)
|
||||
return;
|
||||
|
||||
intel_dip_infoframe_csum(frame);
|
||||
intel_hdmi->write_infoframe(encoder, frame);
|
||||
}
|
||||
|
||||
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
|
||||
{
|
||||
struct dip_infoframe avi_if = {
|
||||
.type = DIP_TYPE_AVI,
|
||||
.ver = DIP_VERSION_AVI,
|
||||
.len = DIP_LEN_AVI,
|
||||
};
|
||||
|
||||
intel_set_infoframe(encoder, &avi_if);
|
||||
}
|
||||
|
||||
static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder)
|
||||
{
|
||||
struct dip_infoframe spd_if;
|
||||
|
||||
memset(&spd_if, 0, sizeof(spd_if));
|
||||
spd_if.type = DIP_TYPE_SPD;
|
||||
spd_if.ver = DIP_VERSION_SPD;
|
||||
spd_if.len = DIP_LEN_SPD;
|
||||
strcpy(spd_if.body.spd.vn, "Intel");
|
||||
strcpy(spd_if.body.spd.pd, "Integrated gfx");
|
||||
spd_if.body.spd.sdi = DIP_SPD_PC;
|
||||
|
||||
intel_set_infoframe(encoder, &spd_if);
|
||||
}
|
||||
|
||||
static void intel_hdmi_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
u32 sdvox;
|
||||
|
||||
sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
sdvox |= intel_hdmi->color_range;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
|
||||
|
||||
if (intel_crtc->bpp > 24)
|
||||
sdvox |= COLOR_FORMAT_12bpc;
|
||||
else
|
||||
sdvox |= COLOR_FORMAT_8bpc;
|
||||
|
||||
/* Required on CPT */
|
||||
if (intel_hdmi->has_hdmi_sink && HAS_PCH_CPT(dev))
|
||||
sdvox |= HDMI_MODE_SELECT;
|
||||
|
||||
if (intel_hdmi->has_audio) {
|
||||
sdvox |= SDVO_AUDIO_ENABLE;
|
||||
sdvox |= SDVO_NULL_PACKETS_DURING_VSYNC;
|
||||
}
|
||||
|
||||
if (intel_crtc->pipe == 1) {
|
||||
if (HAS_PCH_CPT(dev))
|
||||
sdvox |= PORT_TRANS_B_SEL_CPT;
|
||||
else
|
||||
sdvox |= SDVO_PIPE_B_SELECT;
|
||||
}
|
||||
|
||||
I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
|
||||
POSTING_READ(intel_hdmi->sdvox_reg);
|
||||
|
||||
intel_hdmi_set_avi_infoframe(encoder);
|
||||
intel_hdmi_set_spd_infoframe(encoder);
|
||||
}
|
||||
|
||||
static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
u32 temp;
|
||||
|
||||
temp = I915_READ(intel_hdmi->sdvox_reg);
|
||||
|
||||
/* HW workaround, need to toggle enable bit off and on for 12bpc, but
|
||||
* we do this anyway which shows more stable in testing.
|
||||
*/
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
|
||||
POSTING_READ(intel_hdmi->sdvox_reg);
|
||||
}
|
||||
|
||||
if (mode != DRM_MODE_DPMS_ON) {
|
||||
temp &= ~SDVO_ENABLE;
|
||||
} else {
|
||||
temp |= SDVO_ENABLE;
|
||||
}
|
||||
|
||||
I915_WRITE(intel_hdmi->sdvox_reg, temp);
|
||||
POSTING_READ(intel_hdmi->sdvox_reg);
|
||||
|
||||
/* HW workaround, need to write this twice for issue that may result
|
||||
* in first write getting masked.
|
||||
*/
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
I915_WRITE(intel_hdmi->sdvox_reg, temp);
|
||||
POSTING_READ(intel_hdmi->sdvox_reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_hdmi_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 165000)
|
||||
return MODE_CLOCK_HIGH;
|
||||
if (mode->clock < 20000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
intel_hdmi_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
struct edid *edid;
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
|
||||
intel_hdmi->has_hdmi_sink = false;
|
||||
intel_hdmi->has_audio = false;
|
||||
edid = drm_get_edid(connector,
|
||||
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
|
||||
|
||||
if (edid) {
|
||||
if (edid->input & DRM_EDID_INPUT_DIGITAL) {
|
||||
status = connector_status_connected;
|
||||
intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
|
||||
intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
|
||||
}
|
||||
connector->display_info.raw_edid = NULL;
|
||||
kfree(edid);
|
||||
}
|
||||
|
||||
if (status == connector_status_connected) {
|
||||
if (intel_hdmi->force_audio)
|
||||
intel_hdmi->has_audio = intel_hdmi->force_audio > 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int intel_hdmi_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
|
||||
/* We should parse the EDID data and find out if it's an HDMI sink so
|
||||
* we can send audio to it.
|
||||
*/
|
||||
|
||||
return intel_ddc_get_modes(connector,
|
||||
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_hdmi_detect_audio(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
struct edid *edid;
|
||||
bool has_audio = false;
|
||||
|
||||
edid = drm_get_edid(connector,
|
||||
&dev_priv->gmbus[intel_hdmi->ddc_bus].adapter);
|
||||
if (edid) {
|
||||
if (edid->input & DRM_EDID_INPUT_DIGITAL)
|
||||
has_audio = drm_detect_monitor_audio(edid);
|
||||
|
||||
connector->display_info.raw_edid = NULL;
|
||||
kfree(edid);
|
||||
}
|
||||
|
||||
return has_audio;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_hdmi_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_property_set_value(connector, property, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
#if 0
|
||||
if (property == dev_priv->force_audio_property) {
|
||||
int i = val;
|
||||
bool has_audio;
|
||||
|
||||
if (i == intel_hdmi->force_audio)
|
||||
return 0;
|
||||
|
||||
intel_hdmi->force_audio = i;
|
||||
|
||||
if (i == 0)
|
||||
has_audio = intel_hdmi_detect_audio(connector);
|
||||
else
|
||||
has_audio = i > 0;
|
||||
|
||||
if (has_audio == intel_hdmi->has_audio)
|
||||
return 0;
|
||||
|
||||
intel_hdmi->has_audio = has_audio;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (property == dev_priv->broadcast_rgb_property) {
|
||||
if (val == !!intel_hdmi->color_range)
|
||||
return 0;
|
||||
|
||||
intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
return -EINVAL;
|
||||
|
||||
done:
|
||||
if (intel_hdmi->base.base.crtc) {
|
||||
struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
|
||||
drm_crtc_helper_set_mode(crtc, &crtc->mode,
|
||||
crtc->x, crtc->y,
|
||||
crtc->fb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_hdmi_destroy(struct drm_connector *connector)
|
||||
{
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
|
||||
.dpms = intel_hdmi_dpms,
|
||||
.mode_fixup = intel_hdmi_mode_fixup,
|
||||
.prepare = intel_encoder_prepare,
|
||||
.mode_set = intel_hdmi_mode_set,
|
||||
.commit = intel_encoder_commit,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = intel_hdmi_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = intel_hdmi_set_property,
|
||||
.destroy = intel_hdmi_destroy,
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
|
||||
.get_modes = intel_hdmi_get_modes,
|
||||
.mode_valid = intel_hdmi_mode_valid,
|
||||
.best_encoder = intel_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
|
||||
.destroy = intel_encoder_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector)
|
||||
{
|
||||
intel_attach_force_audio_property(connector);
|
||||
intel_attach_broadcast_rgb_property(connector);
|
||||
}
|
||||
|
||||
void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_connector *intel_connector;
|
||||
struct intel_hdmi *intel_hdmi;
|
||||
|
||||
intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
|
||||
if (!intel_hdmi)
|
||||
return;
|
||||
|
||||
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
||||
if (!intel_connector) {
|
||||
kfree(intel_hdmi);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_encoder = &intel_hdmi->base;
|
||||
drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
|
||||
DRM_MODE_ENCODER_TMDS);
|
||||
|
||||
connector = &intel_connector->base;
|
||||
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_HDMIA);
|
||||
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
|
||||
|
||||
intel_encoder->type = INTEL_OUTPUT_HDMI;
|
||||
|
||||
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
||||
connector->interlace_allowed = 0;
|
||||
connector->doublescan_allowed = 0;
|
||||
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
if (sdvox_reg == SDVOB) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
|
||||
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == SDVOC) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
|
||||
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMIB) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
|
||||
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMIC) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
|
||||
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
||||
} else if (sdvox_reg == HDMID) {
|
||||
intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
|
||||
intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
|
||||
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
|
||||
}
|
||||
|
||||
intel_hdmi->sdvox_reg = sdvox_reg;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev))
|
||||
intel_hdmi->write_infoframe = i9xx_write_infoframe;
|
||||
else
|
||||
intel_hdmi->write_infoframe = ironlake_write_infoframe;
|
||||
|
||||
drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
|
||||
|
||||
intel_hdmi_add_properties(intel_hdmi, connector);
|
||||
|
||||
intel_connector_attach_encoder(intel_connector, intel_encoder);
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
|
||||
* 0xd. Failure to do so will result in spurious interrupts being
|
||||
* generated on the port when a cable is not attached.
|
||||
*/
|
||||
if (IS_G4X(dev) && !IS_GM45(dev)) {
|
||||
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
|
||||
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright © 2006-2008,2010 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
@ -31,9 +31,8 @@
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "intel_drv.h"
|
||||
//#include "i915_drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include <syscall.h>
|
||||
|
||||
#define MSEC_PER_SEC 1000L
|
||||
#define USEC_PER_MSEC 1000L
|
||||
|
1051
drivers/video/drm/i915/intel_lvds.c
Normal file
1051
drivers/video/drm/i915/intel_lvds.c
Normal file
File diff suppressed because it is too large
Load Diff
144
drivers/video/drm/i915/intel_modes.c
Normal file
144
drivers/video/drm/i915/intel_modes.c
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
|
||||
* Copyright (c) 2007, 2010 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/fb.h>
|
||||
#include "drmP.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drv.h"
|
||||
|
||||
/**
|
||||
* intel_ddc_probe
|
||||
*
|
||||
*/
|
||||
bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
|
||||
u8 out_buf[] = { 0x0, 0x0};
|
||||
u8 buf[2];
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = 0x50,
|
||||
.flags = 0,
|
||||
.len = 1,
|
||||
.buf = out_buf,
|
||||
},
|
||||
{
|
||||
.addr = 0x50,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 1,
|
||||
.buf = buf,
|
||||
}
|
||||
};
|
||||
|
||||
return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_ddc_get_modes - get modelist from monitor
|
||||
* @connector: DRM connector device to use
|
||||
* @adapter: i2c adapter
|
||||
*
|
||||
* Fetch the EDID information from @connector using the DDC bus.
|
||||
*/
|
||||
int intel_ddc_get_modes(struct drm_connector *connector,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
struct edid *edid;
|
||||
int ret = 0;
|
||||
|
||||
edid = drm_get_edid(connector, adapter);
|
||||
if (edid) {
|
||||
drm_mode_connector_update_edid_property(connector, edid);
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
connector->display_info.raw_edid = NULL;
|
||||
kfree(edid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *force_audio_names[] = {
|
||||
"off",
|
||||
"auto",
|
||||
"on",
|
||||
};
|
||||
|
||||
void
|
||||
intel_attach_force_audio_property(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_property *prop;
|
||||
int i;
|
||||
#if 0
|
||||
prop = dev_priv->force_audio_property;
|
||||
if (prop == NULL) {
|
||||
prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
||||
"audio",
|
||||
ARRAY_SIZE(force_audio_names));
|
||||
if (prop == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(force_audio_names); i++)
|
||||
drm_property_add_enum(prop, i, i-1, force_audio_names[i]);
|
||||
|
||||
dev_priv->force_audio_property = prop;
|
||||
}
|
||||
drm_connector_attach_property(connector, prop, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *broadcast_rgb_names[] = {
|
||||
"Full",
|
||||
"Limited 16:235",
|
||||
};
|
||||
|
||||
void
|
||||
intel_attach_broadcast_rgb_property(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_property *prop;
|
||||
int i;
|
||||
#if 0
|
||||
prop = dev_priv->broadcast_rgb_property;
|
||||
if (prop == NULL) {
|
||||
prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
||||
"Broadcast RGB",
|
||||
ARRAY_SIZE(broadcast_rgb_names));
|
||||
if (prop == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
|
||||
drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
|
||||
|
||||
dev_priv->broadcast_rgb_property = prop;
|
||||
}
|
||||
|
||||
drm_connector_attach_property(connector, prop, 0);
|
||||
#endif
|
||||
}
|
@ -30,12 +30,10 @@
|
||||
//#include <acpi/video.h>
|
||||
#include <linux/errno.h>
|
||||
#include "drmP.h"
|
||||
//#include "i915_drm.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
#include <syscall.h>
|
||||
|
||||
#define PCI_ASLE 0xe4
|
||||
#define PCI_ASLS 0xfc
|
||||
|
||||
|
396
drivers/video/drm/i915/intel_panel.c
Normal file
396
drivers/video/drm/i915/intel_panel.c
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright © 2006-2010 Intel Corporation
|
||||
* Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Dave Airlie <airlied@linux.ie>
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "intel_drv.h"
|
||||
|
||||
static inline int pci_read_config_byte(struct pci_dev *dev, int where,
|
||||
u8 *val)
|
||||
{
|
||||
*val = PciRead8(dev->busnr, dev->devfn, where);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int pci_write_config_byte(struct pci_dev *dev, int where,
|
||||
u8 val)
|
||||
{
|
||||
PciWrite8(dev->busnr, dev->devfn, where, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
|
||||
|
||||
void
|
||||
intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
adjusted_mode->hdisplay = fixed_mode->hdisplay;
|
||||
adjusted_mode->hsync_start = fixed_mode->hsync_start;
|
||||
adjusted_mode->hsync_end = fixed_mode->hsync_end;
|
||||
adjusted_mode->htotal = fixed_mode->htotal;
|
||||
|
||||
adjusted_mode->vdisplay = fixed_mode->vdisplay;
|
||||
adjusted_mode->vsync_start = fixed_mode->vsync_start;
|
||||
adjusted_mode->vsync_end = fixed_mode->vsync_end;
|
||||
adjusted_mode->vtotal = fixed_mode->vtotal;
|
||||
|
||||
adjusted_mode->clock = fixed_mode->clock;
|
||||
|
||||
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
|
||||
}
|
||||
|
||||
/* adjusted_mode has been preset to be the panel's fixed mode */
|
||||
void
|
||||
intel_pch_panel_fitting(struct drm_device *dev,
|
||||
int fitting_mode,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int x, y, width, height;
|
||||
|
||||
x = y = width = height = 0;
|
||||
|
||||
/* Native modes don't need fitting */
|
||||
if (adjusted_mode->hdisplay == mode->hdisplay &&
|
||||
adjusted_mode->vdisplay == mode->vdisplay)
|
||||
goto done;
|
||||
|
||||
switch (fitting_mode) {
|
||||
case DRM_MODE_SCALE_CENTER:
|
||||
width = mode->hdisplay;
|
||||
height = mode->vdisplay;
|
||||
x = (adjusted_mode->hdisplay - width + 1)/2;
|
||||
y = (adjusted_mode->vdisplay - height + 1)/2;
|
||||
break;
|
||||
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
/* Scale but preserve the aspect ratio */
|
||||
{
|
||||
u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
|
||||
u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
|
||||
if (scaled_width > scaled_height) { /* pillar */
|
||||
width = scaled_height / mode->vdisplay;
|
||||
if (width & 1)
|
||||
width++;
|
||||
x = (adjusted_mode->hdisplay - width + 1) / 2;
|
||||
y = 0;
|
||||
height = adjusted_mode->vdisplay;
|
||||
} else if (scaled_width < scaled_height) { /* letter */
|
||||
height = scaled_width / mode->hdisplay;
|
||||
if (height & 1)
|
||||
height++;
|
||||
y = (adjusted_mode->vdisplay - height + 1) / 2;
|
||||
x = 0;
|
||||
width = adjusted_mode->hdisplay;
|
||||
} else {
|
||||
x = y = 0;
|
||||
width = adjusted_mode->hdisplay;
|
||||
height = adjusted_mode->vdisplay;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case DRM_MODE_SCALE_FULLSCREEN:
|
||||
x = y = 0;
|
||||
width = adjusted_mode->hdisplay;
|
||||
height = adjusted_mode->vdisplay;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
dev_priv->pch_pf_pos = (x << 16) | y;
|
||||
dev_priv->pch_pf_size = (width << 16) | height;
|
||||
}
|
||||
|
||||
static int is_backlight_combination_mode(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
return I915_READ(BLC_PWM_CTL2) & BLM_COMBINATION_MODE;
|
||||
|
||||
if (IS_GEN2(dev))
|
||||
return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* Restore the CTL value if it lost, e.g. GPU reset */
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv->dev)) {
|
||||
val = I915_READ(BLC_PWM_PCH_CTL2);
|
||||
if (dev_priv->saveBLC_PWM_CTL2 == 0) {
|
||||
dev_priv->saveBLC_PWM_CTL2 = val;
|
||||
} else if (val == 0) {
|
||||
I915_WRITE(BLC_PWM_PCH_CTL2,
|
||||
dev_priv->saveBLC_PWM_CTL);
|
||||
val = dev_priv->saveBLC_PWM_CTL;
|
||||
}
|
||||
} else {
|
||||
val = I915_READ(BLC_PWM_CTL);
|
||||
if (dev_priv->saveBLC_PWM_CTL == 0) {
|
||||
dev_priv->saveBLC_PWM_CTL = val;
|
||||
dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2);
|
||||
} else if (val == 0) {
|
||||
I915_WRITE(BLC_PWM_CTL,
|
||||
dev_priv->saveBLC_PWM_CTL);
|
||||
I915_WRITE(BLC_PWM_CTL2,
|
||||
dev_priv->saveBLC_PWM_CTL2);
|
||||
val = dev_priv->saveBLC_PWM_CTL;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
u32 intel_panel_get_max_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 max;
|
||||
|
||||
max = i915_read_blc_pwm_ctl(dev_priv);
|
||||
if (max == 0) {
|
||||
/* XXX add code here to query mode clock or hardware clock
|
||||
* and program max PWM appropriately.
|
||||
*/
|
||||
printk(KERN_WARNING "fixme: max PWM is zero.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
max >>= 16;
|
||||
} else {
|
||||
if (IS_PINEVIEW(dev)) {
|
||||
max >>= 17;
|
||||
} else {
|
||||
max >>= 16;
|
||||
if (INTEL_INFO(dev)->gen < 4)
|
||||
max &= ~1;
|
||||
}
|
||||
|
||||
if (is_backlight_combination_mode(dev))
|
||||
max *= 0xff;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
|
||||
return max;
|
||||
}
|
||||
|
||||
u32 intel_panel_get_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 val;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
} else {
|
||||
val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
if (IS_PINEVIEW(dev))
|
||||
val >>= 1;
|
||||
|
||||
if (is_backlight_combination_mode(dev)){
|
||||
u8 lbpc;
|
||||
|
||||
val &= ~1;
|
||||
pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
|
||||
val *= lbpc;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 val = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_CPU_CTL, val | level);
|
||||
}
|
||||
|
||||
void intel_panel_set_backlight(struct drm_device *dev, u32 level)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 tmp;
|
||||
|
||||
DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
|
||||
|
||||
if (HAS_PCH_SPLIT(dev))
|
||||
return intel_pch_panel_set_backlight(dev, level);
|
||||
|
||||
if (is_backlight_combination_mode(dev)){
|
||||
u32 max = intel_panel_get_max_backlight(dev);
|
||||
u8 lbpc;
|
||||
|
||||
lbpc = level * 0xfe / max + 1;
|
||||
level /= lbpc;
|
||||
pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
|
||||
}
|
||||
|
||||
tmp = I915_READ(BLC_PWM_CTL);
|
||||
if (IS_PINEVIEW(dev)) {
|
||||
tmp &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1);
|
||||
level <<= 1;
|
||||
} else
|
||||
tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
I915_WRITE(BLC_PWM_CTL, tmp | level);
|
||||
}
|
||||
|
||||
void intel_panel_disable_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->backlight_enabled) {
|
||||
dev_priv->backlight_level = intel_panel_get_backlight(dev);
|
||||
dev_priv->backlight_enabled = false;
|
||||
}
|
||||
|
||||
intel_panel_set_backlight(dev, 0);
|
||||
}
|
||||
|
||||
void intel_panel_enable_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->backlight_level == 0)
|
||||
dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
|
||||
|
||||
intel_panel_set_backlight(dev, dev_priv->backlight_level);
|
||||
dev_priv->backlight_enabled = true;
|
||||
}
|
||||
|
||||
static void intel_panel_init_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
dev_priv->backlight_level = intel_panel_get_backlight(dev);
|
||||
dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
|
||||
}
|
||||
|
||||
enum drm_connector_status
|
||||
intel_panel_detect(struct drm_device *dev)
|
||||
{
|
||||
#if 0
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
#endif
|
||||
|
||||
if (i915_panel_ignore_lid)
|
||||
return i915_panel_ignore_lid > 0 ?
|
||||
connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
|
||||
/* opregion lid state on HP 2540p is wrong at boot up,
|
||||
* appears to be either the BIOS or Linux ACPI fault */
|
||||
#if 0
|
||||
/* Assume that the BIOS does not lie through the OpRegion... */
|
||||
if (dev_priv->opregion.lid_state)
|
||||
return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
|
||||
connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
#endif
|
||||
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
static int intel_panel_update_status(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(bd);
|
||||
intel_panel_set_backlight(dev, bd->props.brightness);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_panel_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev = bl_get_data(bd);
|
||||
return intel_panel_get_backlight(dev);
|
||||
}
|
||||
|
||||
static const struct backlight_ops intel_panel_bl_ops = {
|
||||
.update_status = intel_panel_update_status,
|
||||
.get_brightness = intel_panel_get_brightness,
|
||||
};
|
||||
|
||||
int intel_panel_setup_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct backlight_properties props;
|
||||
struct drm_connector *connector;
|
||||
|
||||
intel_panel_init_backlight(dev);
|
||||
|
||||
if (dev_priv->int_lvds_connector)
|
||||
connector = dev_priv->int_lvds_connector;
|
||||
else if (dev_priv->int_edp_connector)
|
||||
connector = dev_priv->int_edp_connector;
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = intel_panel_get_max_backlight(dev);
|
||||
dev_priv->backlight =
|
||||
backlight_device_register("intel_backlight",
|
||||
&connector->kdev, dev,
|
||||
&intel_panel_bl_ops, &props);
|
||||
|
||||
if (IS_ERR(dev_priv->backlight)) {
|
||||
DRM_ERROR("Failed to register backlight: %ld\n",
|
||||
PTR_ERR(dev_priv->backlight));
|
||||
dev_priv->backlight = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_panel_destroy_backlight(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
if (dev_priv->backlight)
|
||||
backlight_device_unregister(dev_priv->backlight);
|
||||
}
|
||||
#else
|
||||
int intel_panel_setup_backlight(struct drm_device *dev)
|
||||
{
|
||||
intel_panel_init_backlight(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_panel_destroy_backlight(struct drm_device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
@ -109,7 +109,7 @@ struct intel_ring_buffer {
|
||||
u32 outstanding_lazy_request;
|
||||
|
||||
// wait_queue_head_t irq_queue;
|
||||
// drm_local_map_t map;
|
||||
drm_local_map_t map;
|
||||
|
||||
void *private;
|
||||
};
|
||||
|
2592
drivers/video/drm/i915/intel_sdvo.c
Normal file
2592
drivers/video/drm/i915/intel_sdvo.c
Normal file
File diff suppressed because it is too large
Load Diff
723
drivers/video/drm/i915/intel_sdvo_regs.h
Normal file
723
drivers/video/drm/i915/intel_sdvo_regs.h
Normal file
@ -0,0 +1,723 @@
|
||||
/*
|
||||
* Copyright © 2006-2007 Intel Corporation
|
||||
*
|
||||
* 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:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file SDVO command definitions and structures.
|
||||
*/
|
||||
|
||||
#define SDVO_OUTPUT_FIRST (0)
|
||||
#define SDVO_OUTPUT_TMDS0 (1 << 0)
|
||||
#define SDVO_OUTPUT_RGB0 (1 << 1)
|
||||
#define SDVO_OUTPUT_CVBS0 (1 << 2)
|
||||
#define SDVO_OUTPUT_SVID0 (1 << 3)
|
||||
#define SDVO_OUTPUT_YPRPB0 (1 << 4)
|
||||
#define SDVO_OUTPUT_SCART0 (1 << 5)
|
||||
#define SDVO_OUTPUT_LVDS0 (1 << 6)
|
||||
#define SDVO_OUTPUT_TMDS1 (1 << 8)
|
||||
#define SDVO_OUTPUT_RGB1 (1 << 9)
|
||||
#define SDVO_OUTPUT_CVBS1 (1 << 10)
|
||||
#define SDVO_OUTPUT_SVID1 (1 << 11)
|
||||
#define SDVO_OUTPUT_YPRPB1 (1 << 12)
|
||||
#define SDVO_OUTPUT_SCART1 (1 << 13)
|
||||
#define SDVO_OUTPUT_LVDS1 (1 << 14)
|
||||
#define SDVO_OUTPUT_LAST (14)
|
||||
|
||||
struct intel_sdvo_caps {
|
||||
u8 vendor_id;
|
||||
u8 device_id;
|
||||
u8 device_rev_id;
|
||||
u8 sdvo_version_major;
|
||||
u8 sdvo_version_minor;
|
||||
unsigned int sdvo_inputs_mask:2;
|
||||
unsigned int smooth_scaling:1;
|
||||
unsigned int sharp_scaling:1;
|
||||
unsigned int up_scaling:1;
|
||||
unsigned int down_scaling:1;
|
||||
unsigned int stall_support:1;
|
||||
unsigned int pad:1;
|
||||
u16 output_flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** This matches the EDID DTD structure, more or less */
|
||||
struct intel_sdvo_dtd {
|
||||
struct {
|
||||
u16 clock; /**< pixel clock, in 10kHz units */
|
||||
u8 h_active; /**< lower 8 bits (pixels) */
|
||||
u8 h_blank; /**< lower 8 bits (pixels) */
|
||||
u8 h_high; /**< upper 4 bits each h_active, h_blank */
|
||||
u8 v_active; /**< lower 8 bits (lines) */
|
||||
u8 v_blank; /**< lower 8 bits (lines) */
|
||||
u8 v_high; /**< upper 4 bits each v_active, v_blank */
|
||||
} part1;
|
||||
|
||||
struct {
|
||||
u8 h_sync_off; /**< lower 8 bits, from hblank start */
|
||||
u8 h_sync_width; /**< lower 8 bits (pixels) */
|
||||
/** lower 4 bits each vsync offset, vsync width */
|
||||
u8 v_sync_off_width;
|
||||
/**
|
||||
* 2 high bits of hsync offset, 2 high bits of hsync width,
|
||||
* bits 4-5 of vsync offset, and 2 high bits of vsync width.
|
||||
*/
|
||||
u8 sync_off_width_high;
|
||||
u8 dtd_flags;
|
||||
u8 sdvo_flags;
|
||||
/** bits 6-7 of vsync offset at bits 6-7 */
|
||||
u8 v_sync_off_high;
|
||||
u8 reserved;
|
||||
} part2;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_pixel_clock_range {
|
||||
u16 min; /**< pixel clock, in 10kHz units */
|
||||
u16 max; /**< pixel clock, in 10kHz units */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_preferred_input_timing_args {
|
||||
u16 clock;
|
||||
u16 width;
|
||||
u16 height;
|
||||
u8 interlace:1;
|
||||
u8 scaled:1;
|
||||
u8 pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* I2C registers for SDVO */
|
||||
#define SDVO_I2C_ARG_0 0x07
|
||||
#define SDVO_I2C_ARG_1 0x06
|
||||
#define SDVO_I2C_ARG_2 0x05
|
||||
#define SDVO_I2C_ARG_3 0x04
|
||||
#define SDVO_I2C_ARG_4 0x03
|
||||
#define SDVO_I2C_ARG_5 0x02
|
||||
#define SDVO_I2C_ARG_6 0x01
|
||||
#define SDVO_I2C_ARG_7 0x00
|
||||
#define SDVO_I2C_OPCODE 0x08
|
||||
#define SDVO_I2C_CMD_STATUS 0x09
|
||||
#define SDVO_I2C_RETURN_0 0x0a
|
||||
#define SDVO_I2C_RETURN_1 0x0b
|
||||
#define SDVO_I2C_RETURN_2 0x0c
|
||||
#define SDVO_I2C_RETURN_3 0x0d
|
||||
#define SDVO_I2C_RETURN_4 0x0e
|
||||
#define SDVO_I2C_RETURN_5 0x0f
|
||||
#define SDVO_I2C_RETURN_6 0x10
|
||||
#define SDVO_I2C_RETURN_7 0x11
|
||||
#define SDVO_I2C_VENDOR_BEGIN 0x20
|
||||
|
||||
/* Status results */
|
||||
#define SDVO_CMD_STATUS_POWER_ON 0x0
|
||||
#define SDVO_CMD_STATUS_SUCCESS 0x1
|
||||
#define SDVO_CMD_STATUS_NOTSUPP 0x2
|
||||
#define SDVO_CMD_STATUS_INVALID_ARG 0x3
|
||||
#define SDVO_CMD_STATUS_PENDING 0x4
|
||||
#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5
|
||||
#define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6
|
||||
|
||||
/* SDVO commands, argument/result registers */
|
||||
|
||||
#define SDVO_CMD_RESET 0x01
|
||||
|
||||
/** Returns a struct intel_sdvo_caps */
|
||||
#define SDVO_CMD_GET_DEVICE_CAPS 0x02
|
||||
|
||||
#define SDVO_CMD_GET_FIRMWARE_REV 0x86
|
||||
# define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0
|
||||
# define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1
|
||||
# define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2
|
||||
|
||||
/**
|
||||
* Reports which inputs are trained (managed to sync).
|
||||
*
|
||||
* Devices must have trained within 2 vsyncs of a mode change.
|
||||
*/
|
||||
#define SDVO_CMD_GET_TRAINED_INPUTS 0x03
|
||||
struct intel_sdvo_get_trained_inputs_response {
|
||||
unsigned int input0_trained:1;
|
||||
unsigned int input1_trained:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
/** Returns a struct intel_sdvo_output_flags of active outputs. */
|
||||
#define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04
|
||||
|
||||
/**
|
||||
* Sets the current set of active outputs.
|
||||
*
|
||||
* Takes a struct intel_sdvo_output_flags. Must be preceded by a SET_IN_OUT_MAP
|
||||
* on multi-output devices.
|
||||
*/
|
||||
#define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05
|
||||
|
||||
/**
|
||||
* Returns the current mapping of SDVO inputs to outputs on the device.
|
||||
*
|
||||
* Returns two struct intel_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_GET_IN_OUT_MAP 0x06
|
||||
struct intel_sdvo_in_out_map {
|
||||
u16 in0, in1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current mapping of SDVO inputs to outputs on the device.
|
||||
*
|
||||
* Takes two struct i380_sdvo_output_flags structures.
|
||||
*/
|
||||
#define SDVO_CMD_SET_IN_OUT_MAP 0x07
|
||||
|
||||
/**
|
||||
* Returns a struct intel_sdvo_output_flags of attached displays.
|
||||
*/
|
||||
#define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b
|
||||
|
||||
/**
|
||||
* Returns a struct intel_sdvo_ouptut_flags of displays supporting hot plugging.
|
||||
*/
|
||||
#define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c
|
||||
|
||||
/**
|
||||
* Takes a struct intel_sdvo_output_flags.
|
||||
*/
|
||||
#define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d
|
||||
|
||||
/**
|
||||
* Returns a struct intel_sdvo_output_flags of displays with hot plug
|
||||
* interrupts enabled.
|
||||
*/
|
||||
#define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e
|
||||
|
||||
#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f
|
||||
struct intel_sdvo_get_interrupt_event_source_response {
|
||||
u16 interrupt_status;
|
||||
unsigned int ambient_light_interrupt:1;
|
||||
unsigned int hdmi_audio_encrypt_change:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Selects which input is affected by future input commands.
|
||||
*
|
||||
* Commands affected include SET_INPUT_TIMINGS_PART[12],
|
||||
* GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
|
||||
* GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
|
||||
*/
|
||||
#define SDVO_CMD_SET_TARGET_INPUT 0x10
|
||||
struct intel_sdvo_set_target_input_args {
|
||||
unsigned int target_1:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Takes a struct intel_sdvo_output_flags of which outputs are targeted by
|
||||
* future output commands.
|
||||
*
|
||||
* Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
|
||||
* GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
|
||||
*/
|
||||
#define SDVO_CMD_SET_TARGET_OUTPUT 0x11
|
||||
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12
|
||||
#define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14
|
||||
#define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16
|
||||
#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18
|
||||
#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19
|
||||
/* Part 1 */
|
||||
# define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6
|
||||
# define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7
|
||||
/* Part 2 */
|
||||
# define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0
|
||||
# define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1
|
||||
# define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2
|
||||
# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4
|
||||
# define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7)
|
||||
# define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5)
|
||||
# define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3)
|
||||
# define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1)
|
||||
# define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5
|
||||
# define SDVO_DTD_SDVO_FLAG_STALL (1 << 7)
|
||||
# define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4)
|
||||
# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4)
|
||||
# define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6
|
||||
|
||||
/**
|
||||
* Generates a DTD based on the given width, height, and flags.
|
||||
*
|
||||
* This will be supported by any device supporting scaling or interlaced
|
||||
* modes.
|
||||
*/
|
||||
#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0)
|
||||
# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1)
|
||||
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b
|
||||
#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c
|
||||
|
||||
/** Returns a struct intel_sdvo_pixel_clock_range */
|
||||
#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d
|
||||
/** Returns a struct intel_sdvo_pixel_clock_range */
|
||||
#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e
|
||||
|
||||
/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
|
||||
#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f
|
||||
|
||||
/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
|
||||
#define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20
|
||||
/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
|
||||
#define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21
|
||||
# define SDVO_CLOCK_RATE_MULT_1X (1 << 0)
|
||||
# define SDVO_CLOCK_RATE_MULT_2X (1 << 1)
|
||||
# define SDVO_CLOCK_RATE_MULT_4X (1 << 3)
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27
|
||||
/** 6 bytes of bit flags for TV formats shared by all TV format functions */
|
||||
struct intel_sdvo_tv_format {
|
||||
unsigned int ntsc_m:1;
|
||||
unsigned int ntsc_j:1;
|
||||
unsigned int ntsc_443:1;
|
||||
unsigned int pal_b:1;
|
||||
unsigned int pal_d:1;
|
||||
unsigned int pal_g:1;
|
||||
unsigned int pal_h:1;
|
||||
unsigned int pal_i:1;
|
||||
|
||||
unsigned int pal_m:1;
|
||||
unsigned int pal_n:1;
|
||||
unsigned int pal_nc:1;
|
||||
unsigned int pal_60:1;
|
||||
unsigned int secam_b:1;
|
||||
unsigned int secam_d:1;
|
||||
unsigned int secam_g:1;
|
||||
unsigned int secam_k:1;
|
||||
|
||||
unsigned int secam_k1:1;
|
||||
unsigned int secam_l:1;
|
||||
unsigned int secam_60:1;
|
||||
unsigned int hdtv_std_smpte_240m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_240m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_50:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_274m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_23:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_24:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_25:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_29:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_30:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_50:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_274m_1080p_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_60:1;
|
||||
unsigned int hdtv_std_smpte_295m_1080i_50:1;
|
||||
unsigned int hdtv_std_smpte_295m_1080p_50:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_59:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_60:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_50:1;
|
||||
unsigned int hdtv_std_smpte_293m_480p_59:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_170m_480i_59:1;
|
||||
unsigned int hdtv_std_iturbt601_576i_50:1;
|
||||
unsigned int hdtv_std_iturbt601_576p_50:1;
|
||||
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
||||
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
||||
unsigned int pad:3;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_TV_FORMAT 0x28
|
||||
|
||||
#define SDVO_CMD_SET_TV_FORMAT 0x29
|
||||
|
||||
/** Returns the resolutiosn that can be used with the given TV format */
|
||||
#define SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT 0x83
|
||||
struct intel_sdvo_sdtv_resolution_request {
|
||||
unsigned int ntsc_m:1;
|
||||
unsigned int ntsc_j:1;
|
||||
unsigned int ntsc_443:1;
|
||||
unsigned int pal_b:1;
|
||||
unsigned int pal_d:1;
|
||||
unsigned int pal_g:1;
|
||||
unsigned int pal_h:1;
|
||||
unsigned int pal_i:1;
|
||||
|
||||
unsigned int pal_m:1;
|
||||
unsigned int pal_n:1;
|
||||
unsigned int pal_nc:1;
|
||||
unsigned int pal_60:1;
|
||||
unsigned int secam_b:1;
|
||||
unsigned int secam_d:1;
|
||||
unsigned int secam_g:1;
|
||||
unsigned int secam_k:1;
|
||||
|
||||
unsigned int secam_k1:1;
|
||||
unsigned int secam_l:1;
|
||||
unsigned int secam_60:1;
|
||||
unsigned int pad:5;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_sdtv_resolution_reply {
|
||||
unsigned int res_320x200:1;
|
||||
unsigned int res_320x240:1;
|
||||
unsigned int res_400x300:1;
|
||||
unsigned int res_640x350:1;
|
||||
unsigned int res_640x400:1;
|
||||
unsigned int res_640x480:1;
|
||||
unsigned int res_704x480:1;
|
||||
unsigned int res_704x576:1;
|
||||
|
||||
unsigned int res_720x350:1;
|
||||
unsigned int res_720x400:1;
|
||||
unsigned int res_720x480:1;
|
||||
unsigned int res_720x540:1;
|
||||
unsigned int res_720x576:1;
|
||||
unsigned int res_768x576:1;
|
||||
unsigned int res_800x600:1;
|
||||
unsigned int res_832x624:1;
|
||||
|
||||
unsigned int res_920x766:1;
|
||||
unsigned int res_1024x768:1;
|
||||
unsigned int res_1280x1024:1;
|
||||
unsigned int pad:5;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Get supported resolution with squire pixel aspect ratio that can be
|
||||
scaled for the requested HDTV format */
|
||||
#define SDVO_CMD_GET_SCALED_HDTV_RESOLUTION_SUPPORT 0x85
|
||||
|
||||
struct intel_sdvo_hdtv_resolution_request {
|
||||
unsigned int hdtv_std_smpte_240m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_240m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_260m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_50:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080i_60:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_23:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_274m_1080p_24:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_25:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_29:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_30:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_50:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_59:1;
|
||||
unsigned int hdtv_std_smpte_274m_1080p_60:1;
|
||||
unsigned int hdtv_std_smpte_295m_1080i_50:1;
|
||||
|
||||
unsigned int hdtv_std_smpte_295m_1080p_50:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_59:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_60:1;
|
||||
unsigned int hdtv_std_smpte_296m_720p_50:1;
|
||||
unsigned int hdtv_std_smpte_293m_480p_59:1;
|
||||
unsigned int hdtv_std_smpte_170m_480i_59:1;
|
||||
unsigned int hdtv_std_iturbt601_576i_50:1;
|
||||
unsigned int hdtv_std_iturbt601_576p_50:1;
|
||||
|
||||
unsigned int hdtv_std_eia_7702a_480i_60:1;
|
||||
unsigned int hdtv_std_eia_7702a_480p_60:1;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct intel_sdvo_hdtv_resolution_reply {
|
||||
unsigned int res_640x480:1;
|
||||
unsigned int res_800x600:1;
|
||||
unsigned int res_1024x768:1;
|
||||
unsigned int res_1280x960:1;
|
||||
unsigned int res_1400x1050:1;
|
||||
unsigned int res_1600x1200:1;
|
||||
unsigned int res_1920x1440:1;
|
||||
unsigned int res_2048x1536:1;
|
||||
|
||||
unsigned int res_2560x1920:1;
|
||||
unsigned int res_3200x2400:1;
|
||||
unsigned int res_3840x2880:1;
|
||||
unsigned int pad1:5;
|
||||
|
||||
unsigned int res_848x480:1;
|
||||
unsigned int res_1064x600:1;
|
||||
unsigned int res_1280x720:1;
|
||||
unsigned int res_1360x768:1;
|
||||
unsigned int res_1704x960:1;
|
||||
unsigned int res_1864x1050:1;
|
||||
unsigned int res_1920x1080:1;
|
||||
unsigned int res_2128x1200:1;
|
||||
|
||||
unsigned int res_2560x1400:1;
|
||||
unsigned int res_2728x1536:1;
|
||||
unsigned int res_3408x1920:1;
|
||||
unsigned int res_4264x2400:1;
|
||||
unsigned int res_5120x2880:1;
|
||||
unsigned int pad2:3;
|
||||
|
||||
unsigned int res_768x480:1;
|
||||
unsigned int res_960x600:1;
|
||||
unsigned int res_1152x720:1;
|
||||
unsigned int res_1124x768:1;
|
||||
unsigned int res_1536x960:1;
|
||||
unsigned int res_1680x1050:1;
|
||||
unsigned int res_1728x1080:1;
|
||||
unsigned int res_1920x1200:1;
|
||||
|
||||
unsigned int res_2304x1440:1;
|
||||
unsigned int res_2456x1536:1;
|
||||
unsigned int res_3072x1920:1;
|
||||
unsigned int res_3840x2400:1;
|
||||
unsigned int res_4608x2880:1;
|
||||
unsigned int pad3:3;
|
||||
|
||||
unsigned int res_1280x1024:1;
|
||||
unsigned int pad4:7;
|
||||
|
||||
unsigned int res_1280x768:1;
|
||||
unsigned int pad5:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Get supported power state returns info for encoder and monitor, rely on
|
||||
last SetTargetInput and SetTargetOutput calls */
|
||||
#define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a
|
||||
/* Get power state returns info for encoder and monitor, rely on last
|
||||
SetTargetInput and SetTargetOutput calls */
|
||||
#define SDVO_CMD_GET_POWER_STATE 0x2b
|
||||
#define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b
|
||||
#define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c
|
||||
# define SDVO_ENCODER_STATE_ON (1 << 0)
|
||||
# define SDVO_ENCODER_STATE_STANDBY (1 << 1)
|
||||
# define SDVO_ENCODER_STATE_SUSPEND (1 << 2)
|
||||
# define SDVO_ENCODER_STATE_OFF (1 << 3)
|
||||
# define SDVO_MONITOR_STATE_ON (1 << 4)
|
||||
# define SDVO_MONITOR_STATE_STANDBY (1 << 5)
|
||||
# define SDVO_MONITOR_STATE_SUSPEND (1 << 6)
|
||||
# define SDVO_MONITOR_STATE_OFF (1 << 7)
|
||||
|
||||
#define SDVO_CMD_GET_MAX_PANEL_POWER_SEQUENCING 0x2d
|
||||
#define SDVO_CMD_GET_PANEL_POWER_SEQUENCING 0x2e
|
||||
#define SDVO_CMD_SET_PANEL_POWER_SEQUENCING 0x2f
|
||||
/**
|
||||
* The panel power sequencing parameters are in units of milliseconds.
|
||||
* The high fields are bits 8:9 of the 10-bit values.
|
||||
*/
|
||||
struct sdvo_panel_power_sequencing {
|
||||
u8 t0;
|
||||
u8 t1;
|
||||
u8 t2;
|
||||
u8 t3;
|
||||
u8 t4;
|
||||
|
||||
unsigned int t0_high:2;
|
||||
unsigned int t1_high:2;
|
||||
unsigned int t2_high:2;
|
||||
unsigned int t3_high:2;
|
||||
|
||||
unsigned int t4_high:2;
|
||||
unsigned int pad:6;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_MAX_BACKLIGHT_LEVEL 0x30
|
||||
struct sdvo_max_backlight_reply {
|
||||
u8 max_value;
|
||||
u8 default_value;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_BACKLIGHT_LEVEL 0x31
|
||||
#define SDVO_CMD_SET_BACKLIGHT_LEVEL 0x32
|
||||
|
||||
#define SDVO_CMD_GET_AMBIENT_LIGHT 0x33
|
||||
struct sdvo_get_ambient_light_reply {
|
||||
u16 trip_low;
|
||||
u16 trip_high;
|
||||
u16 value;
|
||||
} __attribute__((packed));
|
||||
#define SDVO_CMD_SET_AMBIENT_LIGHT 0x34
|
||||
struct sdvo_set_ambient_light_reply {
|
||||
u16 trip_low;
|
||||
u16 trip_high;
|
||||
unsigned int enable:1;
|
||||
unsigned int pad:7;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Set display power state */
|
||||
#define SDVO_CMD_SET_DISPLAY_POWER_STATE 0x7d
|
||||
# define SDVO_DISPLAY_STATE_ON (1 << 0)
|
||||
# define SDVO_DISPLAY_STATE_STANDBY (1 << 1)
|
||||
# define SDVO_DISPLAY_STATE_SUSPEND (1 << 2)
|
||||
# define SDVO_DISPLAY_STATE_OFF (1 << 3)
|
||||
|
||||
#define SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS 0x84
|
||||
struct intel_sdvo_enhancements_reply {
|
||||
unsigned int flicker_filter:1;
|
||||
unsigned int flicker_filter_adaptive:1;
|
||||
unsigned int flicker_filter_2d:1;
|
||||
unsigned int saturation:1;
|
||||
unsigned int hue:1;
|
||||
unsigned int brightness:1;
|
||||
unsigned int contrast:1;
|
||||
unsigned int overscan_h:1;
|
||||
|
||||
unsigned int overscan_v:1;
|
||||
unsigned int hpos:1;
|
||||
unsigned int vpos:1;
|
||||
unsigned int sharpness:1;
|
||||
unsigned int dot_crawl:1;
|
||||
unsigned int dither:1;
|
||||
unsigned int tv_chroma_filter:1;
|
||||
unsigned int tv_luma_filter:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Picture enhancement limits below are dependent on the current TV format,
|
||||
* and thus need to be queried and set after it.
|
||||
*/
|
||||
#define SDVO_CMD_GET_MAX_FLICKER_FILTER 0x4d
|
||||
#define SDVO_CMD_GET_MAX_FLICKER_FILTER_ADAPTIVE 0x7b
|
||||
#define SDVO_CMD_GET_MAX_FLICKER_FILTER_2D 0x52
|
||||
#define SDVO_CMD_GET_MAX_SATURATION 0x55
|
||||
#define SDVO_CMD_GET_MAX_HUE 0x58
|
||||
#define SDVO_CMD_GET_MAX_BRIGHTNESS 0x5b
|
||||
#define SDVO_CMD_GET_MAX_CONTRAST 0x5e
|
||||
#define SDVO_CMD_GET_MAX_OVERSCAN_H 0x61
|
||||
#define SDVO_CMD_GET_MAX_OVERSCAN_V 0x64
|
||||
#define SDVO_CMD_GET_MAX_HPOS 0x67
|
||||
#define SDVO_CMD_GET_MAX_VPOS 0x6a
|
||||
#define SDVO_CMD_GET_MAX_SHARPNESS 0x6d
|
||||
#define SDVO_CMD_GET_MAX_TV_CHROMA_FILTER 0x74
|
||||
#define SDVO_CMD_GET_MAX_TV_LUMA_FILTER 0x77
|
||||
struct intel_sdvo_enhancement_limits_reply {
|
||||
u16 max_value;
|
||||
u16 default_value;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_LVDS_PANEL_INFORMATION 0x7f
|
||||
#define SDVO_CMD_SET_LVDS_PANEL_INFORMATION 0x80
|
||||
# define SDVO_LVDS_COLOR_DEPTH_18 (0 << 0)
|
||||
# define SDVO_LVDS_COLOR_DEPTH_24 (1 << 0)
|
||||
# define SDVO_LVDS_CONNECTOR_SPWG (0 << 2)
|
||||
# define SDVO_LVDS_CONNECTOR_OPENLDI (1 << 2)
|
||||
# define SDVO_LVDS_SINGLE_CHANNEL (0 << 4)
|
||||
# define SDVO_LVDS_DUAL_CHANNEL (1 << 4)
|
||||
|
||||
#define SDVO_CMD_GET_FLICKER_FILTER 0x4e
|
||||
#define SDVO_CMD_SET_FLICKER_FILTER 0x4f
|
||||
#define SDVO_CMD_GET_FLICKER_FILTER_ADAPTIVE 0x50
|
||||
#define SDVO_CMD_SET_FLICKER_FILTER_ADAPTIVE 0x51
|
||||
#define SDVO_CMD_GET_FLICKER_FILTER_2D 0x53
|
||||
#define SDVO_CMD_SET_FLICKER_FILTER_2D 0x54
|
||||
#define SDVO_CMD_GET_SATURATION 0x56
|
||||
#define SDVO_CMD_SET_SATURATION 0x57
|
||||
#define SDVO_CMD_GET_HUE 0x59
|
||||
#define SDVO_CMD_SET_HUE 0x5a
|
||||
#define SDVO_CMD_GET_BRIGHTNESS 0x5c
|
||||
#define SDVO_CMD_SET_BRIGHTNESS 0x5d
|
||||
#define SDVO_CMD_GET_CONTRAST 0x5f
|
||||
#define SDVO_CMD_SET_CONTRAST 0x60
|
||||
#define SDVO_CMD_GET_OVERSCAN_H 0x62
|
||||
#define SDVO_CMD_SET_OVERSCAN_H 0x63
|
||||
#define SDVO_CMD_GET_OVERSCAN_V 0x65
|
||||
#define SDVO_CMD_SET_OVERSCAN_V 0x66
|
||||
#define SDVO_CMD_GET_HPOS 0x68
|
||||
#define SDVO_CMD_SET_HPOS 0x69
|
||||
#define SDVO_CMD_GET_VPOS 0x6b
|
||||
#define SDVO_CMD_SET_VPOS 0x6c
|
||||
#define SDVO_CMD_GET_SHARPNESS 0x6e
|
||||
#define SDVO_CMD_SET_SHARPNESS 0x6f
|
||||
#define SDVO_CMD_GET_TV_CHROMA_FILTER 0x75
|
||||
#define SDVO_CMD_SET_TV_CHROMA_FILTER 0x76
|
||||
#define SDVO_CMD_GET_TV_LUMA_FILTER 0x78
|
||||
#define SDVO_CMD_SET_TV_LUMA_FILTER 0x79
|
||||
struct intel_sdvo_enhancements_arg {
|
||||
u16 value;
|
||||
}__attribute__((packed));
|
||||
|
||||
#define SDVO_CMD_GET_DOT_CRAWL 0x70
|
||||
#define SDVO_CMD_SET_DOT_CRAWL 0x71
|
||||
# define SDVO_DOT_CRAWL_ON (1 << 0)
|
||||
# define SDVO_DOT_CRAWL_DEFAULT_ON (1 << 1)
|
||||
|
||||
#define SDVO_CMD_GET_DITHER 0x72
|
||||
#define SDVO_CMD_SET_DITHER 0x73
|
||||
# define SDVO_DITHER_ON (1 << 0)
|
||||
# define SDVO_DITHER_DEFAULT_ON (1 << 1)
|
||||
|
||||
#define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a
|
||||
# define SDVO_CONTROL_BUS_PROM (1 << 0)
|
||||
# define SDVO_CONTROL_BUS_DDC1 (1 << 1)
|
||||
# define SDVO_CONTROL_BUS_DDC2 (1 << 2)
|
||||
# define SDVO_CONTROL_BUS_DDC3 (1 << 3)
|
||||
|
||||
/* HDMI op codes */
|
||||
#define SDVO_CMD_GET_SUPP_ENCODE 0x9d
|
||||
#define SDVO_CMD_GET_ENCODE 0x9e
|
||||
#define SDVO_CMD_SET_ENCODE 0x9f
|
||||
#define SDVO_ENCODE_DVI 0x0
|
||||
#define SDVO_ENCODE_HDMI 0x1
|
||||
#define SDVO_CMD_SET_PIXEL_REPLI 0x8b
|
||||
#define SDVO_CMD_GET_PIXEL_REPLI 0x8c
|
||||
#define SDVO_CMD_GET_COLORIMETRY_CAP 0x8d
|
||||
#define SDVO_CMD_SET_COLORIMETRY 0x8e
|
||||
#define SDVO_COLORIMETRY_RGB256 0x0
|
||||
#define SDVO_COLORIMETRY_RGB220 0x1
|
||||
#define SDVO_COLORIMETRY_YCrCb422 0x3
|
||||
#define SDVO_COLORIMETRY_YCrCb444 0x4
|
||||
#define SDVO_CMD_GET_COLORIMETRY 0x8f
|
||||
#define SDVO_CMD_GET_AUDIO_ENCRYPT_PREFER 0x90
|
||||
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
||||
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
||||
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
||||
#define SDVO_CMD_GET_HBUF_INDEX 0x94
|
||||
#define SDVO_CMD_GET_HBUF_INFO 0x95
|
||||
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
|
||||
#define SDVO_CMD_GET_HBUF_AV_SPLIT 0x97
|
||||
#define SDVO_CMD_SET_HBUF_DATA 0x98
|
||||
#define SDVO_CMD_GET_HBUF_DATA 0x99
|
||||
#define SDVO_CMD_SET_HBUF_TXRATE 0x9a
|
||||
#define SDVO_CMD_GET_HBUF_TXRATE 0x9b
|
||||
#define SDVO_HBUF_TX_DISABLED (0 << 6)
|
||||
#define SDVO_HBUF_TX_ONCE (2 << 6)
|
||||
#define SDVO_HBUF_TX_VSYNC (3 << 6)
|
||||
#define SDVO_CMD_GET_AUDIO_TX_INFO 0x9c
|
||||
#define SDVO_NEED_TO_STALL (1 << 7)
|
||||
|
||||
struct intel_sdvo_encode{
|
||||
u8 dvi_rev;
|
||||
u8 hdmi_rev;
|
||||
} __attribute__ ((packed));
|
@ -26,7 +26,7 @@ u32_t drvEntry(int action, char *cmdline)
|
||||
|
||||
if(!dbg_open(log))
|
||||
{
|
||||
strcpy(log, "/RD/1/DRIVERS/i915.log");
|
||||
strcpy(log, "/HD1/2/i915.log");
|
||||
|
||||
if(!dbg_open(log))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user