Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a4fc5ed6
Commit
a4fc5ed6
authored
Apr 07, 2009
by
Keith Packard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/i915: Add Display Port support
Signed-off-by:
Keith Packard
<
keithp@keithp.com
>
parent
c31c4ba3
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1668 additions
and
6 deletions
+1668
-6
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/Makefile
+2
-0
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_drv.h
+12
-0
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/i915_suspend.c
+33
-1
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_display.c
+102
-5
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp.c
+1098
-0
drivers/gpu/drm/i915/intel_dp.h
drivers/gpu/drm/i915/intel_dp.h
+144
-0
drivers/gpu/drm/i915/intel_dp_i2c.c
drivers/gpu/drm/i915/intel_dp_i2c.c
+272
-0
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_drv.h
+5
-0
No files found.
drivers/gpu/drm/i915/Makefile
View file @
a4fc5ed6
...
...
@@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_crt.o
\
intel_lvds.o
\
intel_bios.o
\
intel_dp.o
\
intel_dp_i2c.o
\
intel_hdmi.o
\
intel_sdvo.o
\
intel_modes.o
\
...
...
drivers/gpu/drm/i915/i915_drv.h
View file @
a4fc5ed6
...
...
@@ -306,6 +306,17 @@ typedef struct drm_i915_private {
u32
saveCURBPOS
;
u32
saveCURBBASE
;
u32
saveCURSIZE
;
u32
saveDP_B
;
u32
saveDP_C
;
u32
saveDP_D
;
u32
savePIPEA_GMCH_DATA_M
;
u32
savePIPEB_GMCH_DATA_M
;
u32
savePIPEA_GMCH_DATA_N
;
u32
savePIPEB_GMCH_DATA_N
;
u32
savePIPEA_DP_LINK_M
;
u32
savePIPEB_DP_LINK_M
;
u32
savePIPEA_DP_LINK_N
;
u32
savePIPEB_DP_LINK_N
;
struct
{
struct
drm_mm
gtt_space
;
...
...
@@ -857,6 +868,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
IS_I915GM(dev)))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev))
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev))
#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
...
...
drivers/gpu/drm/i915/i915_suspend.c
View file @
a4fc5ed6
...
...
@@ -322,6 +322,20 @@ int i915_save_state(struct drm_device *dev)
dev_priv
->
savePP_OFF_DELAYS
=
I915_READ
(
PP_OFF_DELAYS
);
dev_priv
->
savePP_DIVISOR
=
I915_READ
(
PP_DIVISOR
);
/* Display Port state */
if
(
SUPPORTS_INTEGRATED_DP
(
dev
))
{
dev_priv
->
saveDP_B
=
I915_READ
(
DP_B
);
dev_priv
->
saveDP_C
=
I915_READ
(
DP_C
);
dev_priv
->
saveDP_D
=
I915_READ
(
DP_D
);
dev_priv
->
savePIPEA_GMCH_DATA_M
=
I915_READ
(
PIPEA_GMCH_DATA_M
);
dev_priv
->
savePIPEB_GMCH_DATA_M
=
I915_READ
(
PIPEB_GMCH_DATA_M
);
dev_priv
->
savePIPEA_GMCH_DATA_N
=
I915_READ
(
PIPEA_GMCH_DATA_N
);
dev_priv
->
savePIPEB_GMCH_DATA_N
=
I915_READ
(
PIPEB_GMCH_DATA_N
);
dev_priv
->
savePIPEA_DP_LINK_M
=
I915_READ
(
PIPEA_DP_LINK_M
);
dev_priv
->
savePIPEB_DP_LINK_M
=
I915_READ
(
PIPEB_DP_LINK_M
);
dev_priv
->
savePIPEA_DP_LINK_N
=
I915_READ
(
PIPEA_DP_LINK_N
);
dev_priv
->
savePIPEB_DP_LINK_N
=
I915_READ
(
PIPEB_DP_LINK_N
);
}
/* FIXME: save TV & SDVO state */
/* FBC state */
...
...
@@ -404,7 +418,19 @@ int i915_restore_state(struct drm_device *dev)
for
(
i
=
0
;
i
<
8
;
i
++
)
I915_WRITE
(
FENCE_REG_945_8
+
(
i
*
4
),
dev_priv
->
saveFENCE
[
i
+
8
]);
}
/* Display port ratios (must be done before clock is set) */
if
(
SUPPORTS_INTEGRATED_DP
(
dev
))
{
I915_WRITE
(
PIPEA_GMCH_DATA_M
,
dev_priv
->
savePIPEA_GMCH_DATA_M
);
I915_WRITE
(
PIPEB_GMCH_DATA_M
,
dev_priv
->
savePIPEB_GMCH_DATA_M
);
I915_WRITE
(
PIPEA_GMCH_DATA_N
,
dev_priv
->
savePIPEA_GMCH_DATA_N
);
I915_WRITE
(
PIPEB_GMCH_DATA_N
,
dev_priv
->
savePIPEB_GMCH_DATA_N
);
I915_WRITE
(
PIPEA_DP_LINK_M
,
dev_priv
->
savePIPEA_DP_LINK_M
);
I915_WRITE
(
PIPEB_DP_LINK_M
,
dev_priv
->
savePIPEB_DP_LINK_M
);
I915_WRITE
(
PIPEA_DP_LINK_N
,
dev_priv
->
savePIPEA_DP_LINK_N
);
I915_WRITE
(
PIPEB_DP_LINK_N
,
dev_priv
->
savePIPEB_DP_LINK_N
);
}
/* Pipe & plane A info */
/* Prime the clock */
if
(
dev_priv
->
saveDPLL_A
&
DPLL_VCO_ENABLE
)
{
...
...
@@ -518,6 +544,12 @@ int i915_restore_state(struct drm_device *dev)
I915_WRITE
(
PP_DIVISOR
,
dev_priv
->
savePP_DIVISOR
);
I915_WRITE
(
PP_CONTROL
,
dev_priv
->
savePP_CONTROL
);
/* Display Port state */
if
(
SUPPORTS_INTEGRATED_DP
(
dev
))
{
I915_WRITE
(
DP_B
,
dev_priv
->
saveDP_B
);
I915_WRITE
(
DP_C
,
dev_priv
->
saveDP_C
);
I915_WRITE
(
DP_D
,
dev_priv
->
saveDP_D
);
}
/* FIXME: restore TV & SDVO state */
/* FBC info */
...
...
drivers/gpu/drm/i915/intel_display.c
View file @
a4fc5ed6
...
...
@@ -29,6 +29,7 @@
#include "intel_drv.h"
#include "i915_drm.h"
#include "i915_drv.h"
#include "intel_dp.h"
#include "drm_crtc_helper.h"
...
...
@@ -135,10 +136,11 @@ struct intel_limit {
#define INTEL_LIMIT_G4X_HDMI_DAC 5
#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6
#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7
#define INTEL_LIMIT_IGD_SDVO_DAC 8
#define INTEL_LIMIT_IGD_LVDS 9
#define INTEL_LIMIT_IGDNG_SDVO_DAC 10
#define INTEL_LIMIT_IGDNG_LVDS 11
#define INTEL_LIMIT_G4X_DISPLAY_PORT 8
#define INTEL_LIMIT_IGD_SDVO_DAC 9
#define INTEL_LIMIT_IGD_LVDS 10
#define INTEL_LIMIT_IGDNG_SDVO_DAC 11
#define INTEL_LIMIT_IGDNG_LVDS 12
/*The parameter is for SDVO on G4x platform*/
#define G4X_DOT_SDVO_MIN 25000
...
...
@@ -218,6 +220,25 @@ struct intel_limit {
#define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7
#define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0
/*The parameter is for DISPLAY PORT on G4x platform*/
#define G4X_DOT_DISPLAY_PORT_MIN 161670
#define G4X_DOT_DISPLAY_PORT_MAX 227000
#define G4X_N_DISPLAY_PORT_MIN 1
#define G4X_N_DISPLAY_PORT_MAX 2
#define G4X_M_DISPLAY_PORT_MIN 97
#define G4X_M_DISPLAY_PORT_MAX 108
#define G4X_M1_DISPLAY_PORT_MIN 0x10
#define G4X_M1_DISPLAY_PORT_MAX 0x12
#define G4X_M2_DISPLAY_PORT_MIN 0x05
#define G4X_M2_DISPLAY_PORT_MAX 0x06
#define G4X_P_DISPLAY_PORT_MIN 10
#define G4X_P_DISPLAY_PORT_MAX 20
#define G4X_P1_DISPLAY_PORT_MIN 1
#define G4X_P1_DISPLAY_PORT_MAX 2
#define G4X_P2_DISPLAY_PORT_SLOW 10
#define G4X_P2_DISPLAY_PORT_FAST 10
#define G4X_P2_DISPLAY_PORT_LIMIT 0
/* IGDNG */
/* as we calculate clock using (register_value + 2) for
N/M1/M2, so here the range value for them is (actual_value-2).
...
...
@@ -256,6 +277,10 @@ static bool
intel_igdng_find_best_PLL
(
const
intel_limit_t
*
limit
,
struct
drm_crtc
*
crtc
,
int
target
,
int
refclk
,
intel_clock_t
*
best_clock
);
static
bool
intel_find_pll_g4x_dp
(
const
intel_limit_t
*
,
struct
drm_crtc
*
crtc
,
int
target
,
int
refclk
,
intel_clock_t
*
best_clock
);
static
const
intel_limit_t
intel_limits
[]
=
{
{
/* INTEL_LIMIT_I8XX_DVO_DAC */
.
dot
=
{
.
min
=
I8XX_DOT_MIN
,
.
max
=
I8XX_DOT_MAX
},
...
...
@@ -389,6 +414,28 @@ static const intel_limit_t intel_limits[] = {
},
.
find_pll
=
intel_g4x_find_best_PLL
,
},
{
/* INTEL_LIMIT_G4X_DISPLAY_PORT */
.
dot
=
{
.
min
=
G4X_DOT_DISPLAY_PORT_MIN
,
.
max
=
G4X_DOT_DISPLAY_PORT_MAX
},
.
vco
=
{
.
min
=
G4X_VCO_MIN
,
.
max
=
G4X_VCO_MAX
},
.
n
=
{
.
min
=
G4X_N_DISPLAY_PORT_MIN
,
.
max
=
G4X_N_DISPLAY_PORT_MAX
},
.
m
=
{
.
min
=
G4X_M_DISPLAY_PORT_MIN
,
.
max
=
G4X_M_DISPLAY_PORT_MAX
},
.
m1
=
{
.
min
=
G4X_M1_DISPLAY_PORT_MIN
,
.
max
=
G4X_M1_DISPLAY_PORT_MAX
},
.
m2
=
{
.
min
=
G4X_M2_DISPLAY_PORT_MIN
,
.
max
=
G4X_M2_DISPLAY_PORT_MAX
},
.
p
=
{
.
min
=
G4X_P_DISPLAY_PORT_MIN
,
.
max
=
G4X_P_DISPLAY_PORT_MAX
},
.
p1
=
{
.
min
=
G4X_P1_DISPLAY_PORT_MIN
,
.
max
=
G4X_P1_DISPLAY_PORT_MAX
},
.
p2
=
{
.
dot_limit
=
G4X_P2_DISPLAY_PORT_LIMIT
,
.
p2_slow
=
G4X_P2_DISPLAY_PORT_SLOW
,
.
p2_fast
=
G4X_P2_DISPLAY_PORT_FAST
},
.
find_pll
=
intel_find_pll_g4x_dp
,
},
{
/* INTEL_LIMIT_IGD_SDVO */
.
dot
=
{
.
min
=
I9XX_DOT_MIN
,
.
max
=
I9XX_DOT_MAX
},
.
vco
=
{
.
min
=
IGD_VCO_MIN
,
.
max
=
IGD_VCO_MAX
},
...
...
@@ -478,6 +525,8 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
limit
=
&
intel_limits
[
INTEL_LIMIT_G4X_HDMI_DAC
];
}
else
if
(
intel_pipe_has_type
(
crtc
,
INTEL_OUTPUT_SDVO
))
{
limit
=
&
intel_limits
[
INTEL_LIMIT_G4X_SDVO
];
}
else
if
(
intel_pipe_has_type
(
crtc
,
INTEL_OUTPUT_DISPLAYPORT
))
{
limit
=
&
intel_limits
[
INTEL_LIMIT_G4X_DISPLAY_PORT
];
}
else
/* The option is for other outputs */
limit
=
&
intel_limits
[
INTEL_LIMIT_I9XX_SDVO_DAC
];
...
...
@@ -764,6 +813,35 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
return
found
;
}
/* DisplayPort has only two frequencies, 162MHz and 270MHz */
static
bool
intel_find_pll_g4x_dp
(
const
intel_limit_t
*
limit
,
struct
drm_crtc
*
crtc
,
int
target
,
int
refclk
,
intel_clock_t
*
best_clock
)
{
intel_clock_t
clock
;
if
(
target
<
200000
)
{
clock
.
dot
=
161670
;
clock
.
p
=
20
;
clock
.
p1
=
2
;
clock
.
p2
=
10
;
clock
.
n
=
0x01
;
clock
.
m
=
97
;
clock
.
m1
=
0x10
;
clock
.
m2
=
0x05
;
}
else
{
clock
.
dot
=
270000
;
clock
.
p
=
10
;
clock
.
p1
=
1
;
clock
.
p2
=
10
;
clock
.
n
=
0x02
;
clock
.
m
=
108
;
clock
.
m1
=
0x12
;
clock
.
m2
=
0x06
;
}
memcpy
(
best_clock
,
&
clock
,
sizeof
(
intel_clock_t
));
return
true
;
}
void
intel_wait_for_vblank
(
struct
drm_device
*
dev
)
{
...
...
@@ -1541,7 +1619,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
intel_clock_t
clock
;
u32
dpll
=
0
,
fp
=
0
,
dspcntr
,
pipeconf
;
bool
ok
,
is_sdvo
=
false
,
is_dvo
=
false
;
bool
is_crt
=
false
,
is_lvds
=
false
,
is_tv
=
false
;
bool
is_crt
=
false
,
is_lvds
=
false
,
is_tv
=
false
,
is_dp
=
false
;
struct
drm_mode_config
*
mode_config
=
&
dev
->
mode_config
;
struct
drm_connector
*
connector
;
const
intel_limit_t
*
limit
;
...
...
@@ -1585,6 +1663,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
case
INTEL_OUTPUT_ANALOG
:
is_crt
=
true
;
break
;
case
INTEL_OUTPUT_DISPLAYPORT
:
is_dp
=
true
;
break
;
}
num_outputs
++
;
...
...
@@ -1600,6 +1681,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
}
else
{
refclk
=
48000
;
}
/*
* Returns a set of divisors for the desired target clock with the given
...
...
@@ -1662,6 +1744,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
else
if
(
IS_IGDNG
(
dev
))
dpll
|=
(
sdvo_pixel_multiply
-
1
)
<<
PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT
;
}
if
(
is_dp
)
dpll
|=
DPLL_DVO_HIGH_SPEED
;
/* compute bitmask from p1 value */
if
(
IS_IGD
(
dev
))
...
...
@@ -1809,6 +1893,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE
(
lvds_reg
,
lvds
);
I915_READ
(
lvds_reg
);
}
if
(
is_dp
)
intel_dp_set_m_n
(
crtc
,
mode
,
adjusted_mode
);
I915_WRITE
(
fp_reg
,
fp
);
I915_WRITE
(
dpll_reg
,
dpll
);
...
...
@@ -2475,6 +2561,8 @@ static void intel_setup_outputs(struct drm_device *dev)
found
=
intel_sdvo_init
(
dev
,
SDVOB
);
if
(
!
found
&&
SUPPORTS_INTEGRATED_HDMI
(
dev
))
intel_hdmi_init
(
dev
,
SDVOB
);
if
(
!
found
&&
SUPPORTS_INTEGRATED_DP
(
dev
))
intel_dp_init
(
dev
,
DP_B
);
}
/* Before G4X SDVOC doesn't have its own detect register */
...
...
@@ -2487,7 +2575,11 @@ static void intel_setup_outputs(struct drm_device *dev)
found
=
intel_sdvo_init
(
dev
,
SDVOC
);
if
(
!
found
&&
SUPPORTS_INTEGRATED_HDMI
(
dev
))
intel_hdmi_init
(
dev
,
SDVOC
);
if
(
!
found
&&
SUPPORTS_INTEGRATED_DP
(
dev
))
intel_dp_init
(
dev
,
DP_C
);
}
if
(
SUPPORTS_INTEGRATED_DP
(
dev
)
&&
(
I915_READ
(
DP_D
)
&
DP_DETECTED
))
intel_dp_init
(
dev
,
DP_D
);
}
else
intel_dvo_init
(
dev
);
...
...
@@ -2530,6 +2622,11 @@ static void intel_setup_outputs(struct drm_device *dev)
(
1
<<
1
));
clone_mask
=
(
1
<<
INTEL_OUTPUT_TVOUT
);
break
;
case
INTEL_OUTPUT_DISPLAYPORT
:
crtc_mask
=
((
1
<<
0
)
|
(
1
<<
1
));
clone_mask
=
(
1
<<
INTEL_OUTPUT_DISPLAYPORT
);
break
;
}
encoder
->
possible_crtcs
=
crtc_mask
;
encoder
->
possible_clones
=
intel_connector_clones
(
dev
,
clone_mask
);
...
...
drivers/gpu/drm/i915/intel_dp.c
0 → 100644
View file @
a4fc5ed6
This diff is collapsed.
Click to expand it.
drivers/gpu/drm/i915/intel_dp.h
0 → 100644
View file @
a4fc5ed6
/*
* Copyright © 2008 Keith Packard
*
* 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_DP_H_
#define _INTEL_DP_H_
/* From the VESA DisplayPort spec */
#define AUX_NATIVE_WRITE 0x8
#define AUX_NATIVE_READ 0x9
#define AUX_I2C_WRITE 0x0
#define AUX_I2C_READ 0x1
#define AUX_I2C_STATUS 0x2
#define AUX_I2C_MOT 0x4
#define AUX_NATIVE_REPLY_ACK (0x0 << 4)
#define AUX_NATIVE_REPLY_NACK (0x1 << 4)
#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
#define AUX_NATIVE_REPLY_MASK (0x3 << 4)
#define AUX_I2C_REPLY_ACK (0x0 << 6)
#define AUX_I2C_REPLY_NACK (0x1 << 6)
#define AUX_I2C_REPLY_DEFER (0x2 << 6)
#define AUX_I2C_REPLY_MASK (0x3 << 6)
/* AUX CH addresses */
#define DP_LINK_BW_SET 0x100
# define DP_LINK_BW_1_62 0x06
# define DP_LINK_BW_2_7 0x0a
#define DP_LANE_COUNT_SET 0x101
# define DP_LANE_COUNT_MASK 0x0f
# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
#define DP_TRAINING_PATTERN_SET 0x102
# define DP_TRAINING_PATTERN_DISABLE 0
# define DP_TRAINING_PATTERN_1 1
# define DP_TRAINING_PATTERN_2 2
# define DP_TRAINING_PATTERN_MASK 0x3
# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
# define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
# define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
#define DP_TRAINING_LANE0_SET 0x103
#define DP_TRAINING_LANE1_SET 0x104
#define DP_TRAINING_LANE2_SET 0x105
#define DP_TRAINING_LANE3_SET 0x106
# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
# define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
#define DP_DOWNSPREAD_CTRL 0x107
# define DP_SPREAD_AMP_0_5 (1 << 4)
#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
# define DP_SET_ANSI_8B10B (1 << 0)
#define DP_LANE0_1_STATUS 0x202
#define DP_LANE2_3_STATUS 0x203
# define DP_LANE_CR_DONE (1 << 0)
# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
# define DP_LANE_SYMBOL_LOCKED (1 << 2)
#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
#define DP_INTERLANE_ALIGN_DONE (1 << 0)
#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
#define DP_LINK_STATUS_UPDATED (1 << 7)
#define DP_SINK_STATUS 0x205
#define DP_RECEIVE_PORT_0_STATUS (1 << 0)
#define DP_RECEIVE_PORT_1_STATUS (1 << 1)
#define DP_ADJUST_REQUEST_LANE0_1 0x206
#define DP_ADJUST_REQUEST_LANE2_3 0x207
#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
struct
i2c_algo_dp_aux_data
{
bool
running
;
u16
address
;
int
(
*
aux_ch
)
(
struct
i2c_adapter
*
adapter
,
uint8_t
*
send
,
int
send_bytes
,
uint8_t
*
recv
,
int
recv_bytes
);
};
int
i2c_dp_aux_add_bus
(
struct
i2c_adapter
*
adapter
);
#endif
/* _INTEL_DP_H_ */
drivers/gpu/drm/i915/intel_dp_i2c.c
0 → 100644
View file @
a4fc5ed6
/*
* Copyright © 2009 Keith Packard
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/i2c.h>
#include "intel_dp.h"
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
#define MODE_I2C_START 1
#define MODE_I2C_WRITE 2
#define MODE_I2C_READ 4
#define MODE_I2C_STOP 8
static
int
i2c_algo_dp_aux_transaction
(
struct
i2c_adapter
*
adapter
,
int
mode
,
uint8_t
write_byte
,
uint8_t
*
read_byte
)
{
struct
i2c_algo_dp_aux_data
*
algo_data
=
adapter
->
algo_data
;
uint16_t
address
=
algo_data
->
address
;
uint8_t
msg
[
5
];
uint8_t
reply
[
2
];
int
msg_bytes
;
int
reply_bytes
;
int
ret
;
/* Set up the command byte */
if
(
mode
&
MODE_I2C_READ
)
msg
[
0
]
=
AUX_I2C_READ
<<
4
;
else
msg
[
0
]
=
AUX_I2C_WRITE
<<
4
;
if
(
!
(
mode
&
MODE_I2C_STOP
))
msg
[
0
]
|=
AUX_I2C_MOT
<<
4
;
msg
[
1
]
=
address
>>
8
;
msg
[
2
]
=
address
;
switch
(
mode
)
{
case
MODE_I2C_WRITE
:
msg
[
3
]
=
0
;
msg
[
4
]
=
write_byte
;
msg_bytes
=
5
;
reply_bytes
=
1
;
break
;
case
MODE_I2C_READ
:
msg
[
3
]
=
0
;
msg_bytes
=
4
;
reply_bytes
=
2
;
break
;
default:
msg_bytes
=
3
;
reply_bytes
=
1
;
break
;
}
for
(;;)
{
ret
=
(
*
algo_data
->
aux_ch
)(
adapter
,
msg
,
msg_bytes
,
reply
,
reply_bytes
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"aux_ch failed %d
\n
"
,
ret
);
return
ret
;
}
switch
(
reply
[
0
]
&
AUX_I2C_REPLY_MASK
)
{
case
AUX_I2C_REPLY_ACK
:
if
(
mode
==
MODE_I2C_READ
)
{
*
read_byte
=
reply
[
1
];
}
return
reply_bytes
-
1
;
case
AUX_I2C_REPLY_NACK
:
printk
(
KERN_ERR
"aux_ch nack
\n
"
);
return
-
EREMOTEIO
;
case
AUX_I2C_REPLY_DEFER
:
printk
(
KERN_ERR
"aux_ch defer
\n
"
);
udelay
(
100
);
break
;
default:
printk
(
KERN_ERR
"aux_ch invalid reply 0x%02x
\n
"
,
reply
[
0
]);
return
-
EREMOTEIO
;
}
}
}
/*
* I2C over AUX CH
*/
/*
* Send the address. If the I2C link is running, this 'restarts'
* the connection with the new address, this is used for doing
* a write followed by a read (as needed for DDC)
*/
static
int
i2c_algo_dp_aux_address
(
struct
i2c_adapter
*
adapter
,
u16
address
,
bool
reading
)
{
struct
i2c_algo_dp_aux_data
*
algo_data
=
adapter
->
algo_data
;
int
mode
=
MODE_I2C_START
;
int
ret
;
if
(
reading
)
mode
|=
MODE_I2C_READ
;
else
mode
|=
MODE_I2C_WRITE
;
algo_data
->
address
=
address
;
algo_data
->
running
=
true
;
ret
=
i2c_algo_dp_aux_transaction
(
adapter
,
mode
,
0
,
NULL
);
return
ret
;
}
/*
* Stop the I2C transaction. This closes out the link, sending
* a bare address packet with the MOT bit turned off
*/
static
void
i2c_algo_dp_aux_stop
(
struct
i2c_adapter
*
adapter
,
bool
reading
)
{
struct
i2c_algo_dp_aux_data
*
algo_data
=
adapter
->
algo_data
;
int
mode
=
MODE_I2C_STOP
;
if
(
reading
)
mode
|=
MODE_I2C_READ
;
else
mode
|=
MODE_I2C_WRITE
;
if
(
algo_data
->
running
)
{
(
void
)
i2c_algo_dp_aux_transaction
(
adapter
,
mode
,
0
,
NULL
);
algo_data
->
running
=
false
;
}
}
/*
* Write a single byte to the current I2C address, the
* the I2C link must be running or this returns -EIO
*/
static
int
i2c_algo_dp_aux_put_byte
(
struct
i2c_adapter
*
adapter
,
u8
byte
)
{
struct
i2c_algo_dp_aux_data
*
algo_data
=
adapter
->
algo_data
;
int
ret
;
if
(
!
algo_data
->
running
)
return
-
EIO
;
ret
=
i2c_algo_dp_aux_transaction
(
adapter
,
MODE_I2C_WRITE
,
byte
,
NULL
);
return
ret
;
}
/*
* Read a single byte from the current I2C address, the
* I2C link must be running or this returns -EIO
*/
static
int
i2c_algo_dp_aux_get_byte
(
struct
i2c_adapter
*
adapter
,
u8
*
byte_ret
)
{
struct
i2c_algo_dp_aux_data
*
algo_data
=
adapter
->
algo_data
;
int
ret
;
if
(
!
algo_data
->
running
)
return
-
EIO
;
ret
=
i2c_algo_dp_aux_transaction
(
adapter
,
MODE_I2C_READ
,
0
,
byte_ret
);
return
ret
;
}
static
int
i2c_algo_dp_aux_xfer
(
struct
i2c_adapter
*
adapter
,
struct
i2c_msg
*
msgs
,
int
num
)
{
int
ret
=
0
;
bool
reading
=
false
;
int
m
;
int
b
;
for
(
m
=
0
;
m
<
num
;
m
++
)
{
u16
len
=
msgs
[
m
].
len
;
u8
*
buf
=
msgs
[
m
].
buf
;
reading
=
(
msgs
[
m
].
flags
&
I2C_M_RD
)
!=
0
;
ret
=
i2c_algo_dp_aux_address
(
adapter
,
msgs
[
m
].
addr
,
reading
);
if
(
ret
<
0
)
break
;
if
(
reading
)
{
for
(
b
=
0
;
b
<
len
;
b
++
)
{
ret
=
i2c_algo_dp_aux_get_byte
(
adapter
,
&
buf
[
b
]);
if
(
ret
<
0
)
break
;
}
}
else
{
for
(
b
=
0
;
b
<
len
;
b
++
)
{
ret
=
i2c_algo_dp_aux_put_byte
(
adapter
,
buf
[
b
]);
if
(
ret
<
0
)
break
;
}
}
if
(
ret
<
0
)
break
;
}
if
(
ret
>=
0
)
ret
=
num
;
i2c_algo_dp_aux_stop
(
adapter
,
reading
);
printk
(
KERN_ERR
"dp_aux_xfer return %d
\n
"
,
ret
);
return
ret
;
}
static
u32
i2c_algo_dp_aux_functionality
(
struct
i2c_adapter
*
adapter
)
{
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
|
I2C_FUNC_SMBUS_READ_BLOCK_DATA
|
I2C_FUNC_SMBUS_BLOCK_PROC_CALL
|
I2C_FUNC_10BIT_ADDR
;
}
static
const
struct
i2c_algorithm
i2c_dp_aux_algo
=
{
.
master_xfer
=
i2c_algo_dp_aux_xfer
,
.
functionality
=
i2c_algo_dp_aux_functionality
,
};
static
void
i2c_dp_aux_reset_bus
(
struct
i2c_adapter
*
adapter
)
{
(
void
)
i2c_algo_dp_aux_address
(
adapter
,
0
,
false
);
(
void
)
i2c_algo_dp_aux_stop
(
adapter
,
false
);
}
static
int
i2c_dp_aux_prepare_bus
(
struct
i2c_adapter
*
adapter
)
{
adapter
->
algo
=
&
i2c_dp_aux_algo
;
adapter
->
retries
=
3
;
i2c_dp_aux_reset_bus
(
adapter
);
return
0
;
}
int
i2c_dp_aux_add_bus
(
struct
i2c_adapter
*
adapter
)
{
int
error
;
error
=
i2c_dp_aux_prepare_bus
(
adapter
);
if
(
error
)
return
error
;
error
=
i2c_add_adapter
(
adapter
);
return
error
;
}
EXPORT_SYMBOL
(
i2c_dp_aux_add_bus
);
drivers/gpu/drm/i915/intel_drv.h
View file @
a4fc5ed6
...
...
@@ -54,6 +54,7 @@
#define INTEL_OUTPUT_LVDS 4
#define INTEL_OUTPUT_TVOUT 5
#define INTEL_OUTPUT_HDMI 6
#define INTEL_OUTPUT_DISPLAYPORT 7
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
...
...
@@ -116,6 +117,10 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
extern
void
intel_dvo_init
(
struct
drm_device
*
dev
);
extern
void
intel_tv_init
(
struct
drm_device
*
dev
);
extern
void
intel_lvds_init
(
struct
drm_device
*
dev
);
extern
void
intel_dp_init
(
struct
drm_device
*
dev
,
int
dp_reg
);
void
intel_dp_set_m_n
(
struct
drm_crtc
*
crtc
,
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
);
extern
void
intel_crtc_load_lut
(
struct
drm_crtc
*
crtc
);
extern
void
intel_encoder_prepare
(
struct
drm_encoder
*
encoder
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment