Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
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 @@ out:
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