Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
86a3073e
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
86a3073e
编写于
10月 20, 2011
作者:
K
Keith Packard
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'edp-training-fixes' into drm-intel-next
Conflicts: drivers/gpu/drm/i915/intel_dp.c Just whitespace change conflicts
上级
0ac225e5
32ce697c
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
414 addition
and
122 deletion
+414
-122
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_drv.h
+0
-2
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_irq.c
+28
-0
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_reg.h
+24
-1
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_bios.h
+4
-4
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp.c
+358
-115
未找到文件。
drivers/gpu/drm/i915/i915_drv.h
浏览文件 @
86a3073e
...
@@ -349,7 +349,6 @@ typedef struct drm_i915_private {
...
@@ -349,7 +349,6 @@ typedef struct drm_i915_private {
/* LVDS info */
/* LVDS info */
int
backlight_level
;
/* restore backlight to this value */
int
backlight_level
;
/* restore backlight to this value */
bool
backlight_enabled
;
bool
backlight_enabled
;
struct
drm_display_mode
*
panel_fixed_mode
;
struct
drm_display_mode
*
lfp_lvds_vbt_mode
;
/* if any */
struct
drm_display_mode
*
lfp_lvds_vbt_mode
;
/* if any */
struct
drm_display_mode
*
sdvo_lvds_vbt_mode
;
/* if any */
struct
drm_display_mode
*
sdvo_lvds_vbt_mode
;
/* if any */
...
@@ -674,7 +673,6 @@ typedef struct drm_i915_private {
...
@@ -674,7 +673,6 @@ typedef struct drm_i915_private {
unsigned
int
lvds_border_bits
;
unsigned
int
lvds_border_bits
;
/* Panel fitter placement and size for Ironlake+ */
/* Panel fitter placement and size for Ironlake+ */
u32
pch_pf_pos
,
pch_pf_size
;
u32
pch_pf_pos
,
pch_pf_size
;
int
panel_t3
,
panel_t12
;
struct
drm_crtc
*
plane_to_crtc_mapping
[
2
];
struct
drm_crtc
*
plane_to_crtc_mapping
[
2
];
struct
drm_crtc
*
pipe_to_crtc_mapping
[
2
];
struct
drm_crtc
*
pipe_to_crtc_mapping
[
2
];
...
...
drivers/gpu/drm/i915/i915_irq.c
浏览文件 @
86a3073e
...
@@ -1777,6 +1777,26 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
...
@@ -1777,6 +1777,26 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
POSTING_READ
(
SDEIER
);
POSTING_READ
(
SDEIER
);
}
}
/*
* Enable digital hotplug on the PCH, and configure the DP short pulse
* duration to 2ms (which is the minimum in the Display Port spec)
*
* This register is the same on all known PCH chips.
*/
static
void
ironlake_enable_pch_hotplug
(
struct
drm_device
*
dev
)
{
drm_i915_private_t
*
dev_priv
=
(
drm_i915_private_t
*
)
dev
->
dev_private
;
u32
hotplug
;
hotplug
=
I915_READ
(
PCH_PORT_HOTPLUG
);
hotplug
&=
~
(
PORTD_PULSE_DURATION_MASK
|
PORTC_PULSE_DURATION_MASK
|
PORTB_PULSE_DURATION_MASK
);
hotplug
|=
PORTD_HOTPLUG_ENABLE
|
PORTD_PULSE_DURATION_2ms
;
hotplug
|=
PORTC_HOTPLUG_ENABLE
|
PORTC_PULSE_DURATION_2ms
;
hotplug
|=
PORTB_HOTPLUG_ENABLE
|
PORTB_PULSE_DURATION_2ms
;
I915_WRITE
(
PCH_PORT_HOTPLUG
,
hotplug
);
}
static
int
ironlake_irq_postinstall
(
struct
drm_device
*
dev
)
static
int
ironlake_irq_postinstall
(
struct
drm_device
*
dev
)
{
{
drm_i915_private_t
*
dev_priv
=
(
drm_i915_private_t
*
)
dev
->
dev_private
;
drm_i915_private_t
*
dev_priv
=
(
drm_i915_private_t
*
)
dev
->
dev_private
;
...
@@ -1839,6 +1859,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
...
@@ -1839,6 +1859,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
I915_WRITE
(
SDEIER
,
hotplug_mask
);
I915_WRITE
(
SDEIER
,
hotplug_mask
);
POSTING_READ
(
SDEIER
);
POSTING_READ
(
SDEIER
);
ironlake_enable_pch_hotplug
(
dev
);
if
(
IS_IRONLAKE_M
(
dev
))
{
if
(
IS_IRONLAKE_M
(
dev
))
{
/* Clear & enable PCU event interrupts */
/* Clear & enable PCU event interrupts */
I915_WRITE
(
DEIIR
,
DE_PCU_EVENT
);
I915_WRITE
(
DEIIR
,
DE_PCU_EVENT
);
...
@@ -1896,6 +1918,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
...
@@ -1896,6 +1918,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
I915_WRITE
(
SDEIER
,
hotplug_mask
);
I915_WRITE
(
SDEIER
,
hotplug_mask
);
POSTING_READ
(
SDEIER
);
POSTING_READ
(
SDEIER
);
ironlake_enable_pch_hotplug
(
dev
);
return
0
;
return
0
;
}
}
...
@@ -2020,6 +2044,10 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
...
@@ -2020,6 +2044,10 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
I915_WRITE
(
GTIMR
,
0xffffffff
);
I915_WRITE
(
GTIMR
,
0xffffffff
);
I915_WRITE
(
GTIER
,
0x0
);
I915_WRITE
(
GTIER
,
0x0
);
I915_WRITE
(
GTIIR
,
I915_READ
(
GTIIR
));
I915_WRITE
(
GTIIR
,
I915_READ
(
GTIIR
));
I915_WRITE
(
SDEIMR
,
0xffffffff
);
I915_WRITE
(
SDEIER
,
0x0
);
I915_WRITE
(
SDEIIR
,
I915_READ
(
SDEIIR
));
}
}
static
void
i915_driver_irq_uninstall
(
struct
drm_device
*
dev
)
static
void
i915_driver_irq_uninstall
(
struct
drm_device
*
dev
)
...
...
drivers/gpu/drm/i915/i915_reg.h
浏览文件 @
86a3073e
...
@@ -2916,12 +2916,13 @@
...
@@ -2916,12 +2916,13 @@
#define SDEIER 0xc400c
#define SDEIER 0xc400c
/* digital port hotplug */
/* digital port hotplug */
#define PCH_PORT_HOTPLUG 0xc4030
#define PCH_PORT_HOTPLUG 0xc4030
/* SHOTPLUG_CTL */
#define PORTD_HOTPLUG_ENABLE (1 << 20)
#define PORTD_HOTPLUG_ENABLE (1 << 20)
#define PORTD_PULSE_DURATION_2ms (0)
#define PORTD_PULSE_DURATION_2ms (0)
#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
#define PORTD_PULSE_DURATION_4_5ms (1 << 18)
#define PORTD_PULSE_DURATION_6ms (2 << 18)
#define PORTD_PULSE_DURATION_6ms (2 << 18)
#define PORTD_PULSE_DURATION_100ms (3 << 18)
#define PORTD_PULSE_DURATION_100ms (3 << 18)
#define PORTD_PULSE_DURATION_MASK (3 << 18)
#define PORTD_HOTPLUG_NO_DETECT (0)
#define PORTD_HOTPLUG_NO_DETECT (0)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
#define PORTD_HOTPLUG_LONG_DETECT (1 << 17)
...
@@ -2930,6 +2931,7 @@
...
@@ -2930,6 +2931,7 @@
#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
#define PORTC_PULSE_DURATION_4_5ms (1 << 10)
#define PORTC_PULSE_DURATION_6ms (2 << 10)
#define PORTC_PULSE_DURATION_6ms (2 << 10)
#define PORTC_PULSE_DURATION_100ms (3 << 10)
#define PORTC_PULSE_DURATION_100ms (3 << 10)
#define PORTC_PULSE_DURATION_MASK (3 << 10)
#define PORTC_HOTPLUG_NO_DETECT (0)
#define PORTC_HOTPLUG_NO_DETECT (0)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
#define PORTC_HOTPLUG_LONG_DETECT (1 << 9)
...
@@ -2938,6 +2940,7 @@
...
@@ -2938,6 +2940,7 @@
#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
#define PORTB_PULSE_DURATION_4_5ms (1 << 2)
#define PORTB_PULSE_DURATION_6ms (2 << 2)
#define PORTB_PULSE_DURATION_6ms (2 << 2)
#define PORTB_PULSE_DURATION_100ms (3 << 2)
#define PORTB_PULSE_DURATION_100ms (3 << 2)
#define PORTB_PULSE_DURATION_MASK (3 << 2)
#define PORTB_HOTPLUG_NO_DETECT (0)
#define PORTB_HOTPLUG_NO_DETECT (0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
#define PORTB_HOTPLUG_LONG_DETECT (1 << 1)
...
@@ -3321,15 +3324,35 @@
...
@@ -3321,15 +3324,35 @@
#define PCH_PP_STATUS 0xc7200
#define PCH_PP_STATUS 0xc7200
#define PCH_PP_CONTROL 0xc7204
#define PCH_PP_CONTROL 0xc7204
#define PANEL_UNLOCK_REGS (0xabcd << 16)
#define PANEL_UNLOCK_REGS (0xabcd << 16)
#define PANEL_UNLOCK_MASK (0xffff << 16)
#define EDP_FORCE_VDD (1 << 3)
#define EDP_FORCE_VDD (1 << 3)
#define EDP_BLC_ENABLE (1 << 2)
#define EDP_BLC_ENABLE (1 << 2)
#define PANEL_POWER_RESET (1 << 1)
#define PANEL_POWER_RESET (1 << 1)
#define PANEL_POWER_OFF (0 << 0)
#define PANEL_POWER_OFF (0 << 0)
#define PANEL_POWER_ON (1 << 0)
#define PANEL_POWER_ON (1 << 0)
#define PCH_PP_ON_DELAYS 0xc7208
#define PCH_PP_ON_DELAYS 0xc7208
#define PANEL_PORT_SELECT_MASK (3 << 30)
#define PANEL_PORT_SELECT_LVDS (0 << 30)
#define PANEL_PORT_SELECT_DPA (1 << 30)
#define EDP_PANEL (1 << 30)
#define EDP_PANEL (1 << 30)
#define PANEL_PORT_SELECT_DPC (2 << 30)
#define PANEL_PORT_SELECT_DPD (3 << 30)
#define PANEL_POWER_UP_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_UP_DELAY_SHIFT 16
#define PANEL_LIGHT_ON_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_ON_DELAY_SHIFT 0
#define PCH_PP_OFF_DELAYS 0xc720c
#define PCH_PP_OFF_DELAYS 0xc720c
#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000)
#define PANEL_POWER_DOWN_DELAY_SHIFT 16
#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff)
#define PANEL_LIGHT_OFF_DELAY_SHIFT 0
#define PCH_PP_DIVISOR 0xc7210
#define PCH_PP_DIVISOR 0xc7210
#define PP_REFERENCE_DIVIDER_MASK (0xffffff00)
#define PP_REFERENCE_DIVIDER_SHIFT 8
#define PANEL_POWER_CYCLE_DELAY_MASK (0x1f)
#define PANEL_POWER_CYCLE_DELAY_SHIFT 0
#define PCH_DP_B 0xe4100
#define PCH_DP_B 0xe4100
#define PCH_DPB_AUX_CH_CTL 0xe4110
#define PCH_DPB_AUX_CH_CTL 0xe4110
...
...
drivers/gpu/drm/i915/intel_bios.h
浏览文件 @
86a3073e
/*
/*
* Copyright 2006 Intel Corporation
* Copyright
©
2006 Intel Corporation
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* copy of this software and associated documentation files (the "Software"),
...
@@ -446,11 +446,11 @@ struct bdb_driver_features {
...
@@ -446,11 +446,11 @@ struct bdb_driver_features {
#define EDP_VSWING_1_2V 3
#define EDP_VSWING_1_2V 3
struct
edp_power_seq
{
struct
edp_power_seq
{
u16
t3
;
u16
t
1_t
3
;
u16
t
7
;
u16
t
8
;
u16
t9
;
u16
t9
;
u16
t10
;
u16
t10
;
u16
t12
;
u16
t1
1_t1
2
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
struct
edp_link_params
{
struct
edp_link_params
{
...
...
drivers/gpu/drm/i915/intel_dp.c
浏览文件 @
86a3073e
...
@@ -59,6 +59,15 @@ struct intel_dp {
...
@@ -59,6 +59,15 @@ struct intel_dp {
bool
is_pch_edp
;
bool
is_pch_edp
;
uint8_t
train_set
[
4
];
uint8_t
train_set
[
4
];
uint8_t
link_status
[
DP_LINK_STATUS_SIZE
];
uint8_t
link_status
[
DP_LINK_STATUS_SIZE
];
int
panel_power_up_delay
;
int
panel_power_down_delay
;
int
panel_power_cycle_delay
;
int
backlight_on_delay
;
int
backlight_off_delay
;
struct
drm_display_mode
*
panel_fixed_mode
;
/* for eDP */
struct
delayed_work
panel_vdd_work
;
bool
want_panel_vdd
;
unsigned
long
panel_off_jiffies
;
};
};
/**
/**
...
@@ -200,16 +209,14 @@ intel_dp_mode_valid(struct drm_connector *connector,
...
@@ -200,16 +209,14 @@ intel_dp_mode_valid(struct drm_connector *connector,
struct
drm_display_mode
*
mode
)
struct
drm_display_mode
*
mode
)
{
{
struct
intel_dp
*
intel_dp
=
intel_attached_dp
(
connector
);
struct
intel_dp
*
intel_dp
=
intel_attached_dp
(
connector
);
struct
drm_device
*
dev
=
connector
->
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
int
max_link_clock
=
intel_dp_link_clock
(
intel_dp_max_link_bw
(
intel_dp
));
int
max_link_clock
=
intel_dp_link_clock
(
intel_dp_max_link_bw
(
intel_dp
));
int
max_lanes
=
intel_dp_max_lane_count
(
intel_dp
);
int
max_lanes
=
intel_dp_max_lane_count
(
intel_dp
);
if
(
is_edp
(
intel_dp
)
&&
dev_priv
->
panel_fixed_mode
)
{
if
(
is_edp
(
intel_dp
)
&&
intel_dp
->
panel_fixed_mode
)
{
if
(
mode
->
hdisplay
>
dev_priv
->
panel_fixed_mode
->
hdisplay
)
if
(
mode
->
hdisplay
>
intel_dp
->
panel_fixed_mode
->
hdisplay
)
return
MODE_PANEL
;
return
MODE_PANEL
;
if
(
mode
->
vdisplay
>
dev_priv
->
panel_fixed_mode
->
vdisplay
)
if
(
mode
->
vdisplay
>
intel_dp
->
panel_fixed_mode
->
vdisplay
)
return
MODE_PANEL
;
return
MODE_PANEL
;
}
}
...
@@ -279,6 +286,38 @@ intel_hrawclk(struct drm_device *dev)
...
@@ -279,6 +286,38 @@ intel_hrawclk(struct drm_device *dev)
}
}
}
}
static
bool
ironlake_edp_have_panel_power
(
struct
intel_dp
*
intel_dp
)
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
return
(
I915_READ
(
PCH_PP_STATUS
)
&
PP_ON
)
!=
0
;
}
static
bool
ironlake_edp_have_panel_vdd
(
struct
intel_dp
*
intel_dp
)
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
return
(
I915_READ
(
PCH_PP_CONTROL
)
&
EDP_FORCE_VDD
)
!=
0
;
}
static
void
intel_dp_check_edp
(
struct
intel_dp
*
intel_dp
)
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
if
(
!
is_edp
(
intel_dp
))
return
;
if
(
!
ironlake_edp_have_panel_power
(
intel_dp
)
&&
!
ironlake_edp_have_panel_vdd
(
intel_dp
))
{
WARN
(
1
,
"eDP powered off while attempting aux channel communication.
\n
"
);
DRM_DEBUG_KMS
(
"Status 0x%08x Control 0x%08x
\n
"
,
I915_READ
(
PCH_PP_STATUS
),
I915_READ
(
PCH_PP_CONTROL
));
}
}
static
int
static
int
intel_dp_aux_ch
(
struct
intel_dp
*
intel_dp
,
intel_dp_aux_ch
(
struct
intel_dp
*
intel_dp
,
uint8_t
*
send
,
int
send_bytes
,
uint8_t
*
send
,
int
send_bytes
,
...
@@ -295,6 +334,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
...
@@ -295,6 +334,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
uint32_t
aux_clock_divider
;
uint32_t
aux_clock_divider
;
int
try
,
precharge
;
int
try
,
precharge
;
intel_dp_check_edp
(
intel_dp
);
/* The clock divider is based off the hrawclk,
/* The clock divider is based off the hrawclk,
* and would like to run at 2MHz. So, take the
* and would like to run at 2MHz. So, take the
* hrawclk value and divide by 2 and use that
* hrawclk value and divide by 2 and use that
...
@@ -408,6 +448,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
...
@@ -408,6 +448,7 @@ intel_dp_aux_native_write(struct intel_dp *intel_dp,
int
msg_bytes
;
int
msg_bytes
;
uint8_t
ack
;
uint8_t
ack
;
intel_dp_check_edp
(
intel_dp
);
if
(
send_bytes
>
16
)
if
(
send_bytes
>
16
)
return
-
1
;
return
-
1
;
msg
[
0
]
=
AUX_NATIVE_WRITE
<<
4
;
msg
[
0
]
=
AUX_NATIVE_WRITE
<<
4
;
...
@@ -450,6 +491,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
...
@@ -450,6 +491,7 @@ intel_dp_aux_native_read(struct intel_dp *intel_dp,
uint8_t
ack
;
uint8_t
ack
;
int
ret
;
int
ret
;
intel_dp_check_edp
(
intel_dp
);
msg
[
0
]
=
AUX_NATIVE_READ
<<
4
;
msg
[
0
]
=
AUX_NATIVE_READ
<<
4
;
msg
[
1
]
=
address
>>
8
;
msg
[
1
]
=
address
>>
8
;
msg
[
2
]
=
address
&
0xff
;
msg
[
2
]
=
address
&
0xff
;
...
@@ -493,6 +535,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
...
@@ -493,6 +535,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
int
reply_bytes
;
int
reply_bytes
;
int
ret
;
int
ret
;
intel_dp_check_edp
(
intel_dp
);
/* Set up the command byte */
/* Set up the command byte */
if
(
mode
&
MODE_I2C_READ
)
if
(
mode
&
MODE_I2C_READ
)
msg
[
0
]
=
AUX_I2C_READ
<<
4
;
msg
[
0
]
=
AUX_I2C_READ
<<
4
;
...
@@ -573,10 +616,15 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
...
@@ -573,10 +616,15 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
return
-
EREMOTEIO
;
return
-
EREMOTEIO
;
}
}
static
void
ironlake_edp_panel_vdd_on
(
struct
intel_dp
*
intel_dp
);
static
void
ironlake_edp_panel_vdd_off
(
struct
intel_dp
*
intel_dp
,
bool
sync
);
static
int
static
int
intel_dp_i2c_init
(
struct
intel_dp
*
intel_dp
,
intel_dp_i2c_init
(
struct
intel_dp
*
intel_dp
,
struct
intel_connector
*
intel_connector
,
const
char
*
name
)
struct
intel_connector
*
intel_connector
,
const
char
*
name
)
{
{
int
ret
;
DRM_DEBUG_KMS
(
"i2c_init %s
\n
"
,
name
);
DRM_DEBUG_KMS
(
"i2c_init %s
\n
"
,
name
);
intel_dp
->
algo
.
running
=
false
;
intel_dp
->
algo
.
running
=
false
;
intel_dp
->
algo
.
address
=
0
;
intel_dp
->
algo
.
address
=
0
;
...
@@ -590,7 +638,10 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
...
@@ -590,7 +638,10 @@ intel_dp_i2c_init(struct intel_dp *intel_dp,
intel_dp
->
adapter
.
algo_data
=
&
intel_dp
->
algo
;
intel_dp
->
adapter
.
algo_data
=
&
intel_dp
->
algo
;
intel_dp
->
adapter
.
dev
.
parent
=
&
intel_connector
->
base
.
kdev
;
intel_dp
->
adapter
.
dev
.
parent
=
&
intel_connector
->
base
.
kdev
;
return
i2c_dp_aux_add_bus
(
&
intel_dp
->
adapter
);
ironlake_edp_panel_vdd_on
(
intel_dp
);
ret
=
i2c_dp_aux_add_bus
(
&
intel_dp
->
adapter
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
return
ret
;
}
}
static
bool
static
bool
...
@@ -598,22 +649,21 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
...
@@ -598,22 +649,21 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct
drm_display_mode
*
adjusted_mode
)
struct
drm_display_mode
*
adjusted_mode
)
{
{
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
int
lane_count
,
clock
;
int
lane_count
,
clock
;
int
max_lane_count
=
intel_dp_max_lane_count
(
intel_dp
);
int
max_lane_count
=
intel_dp_max_lane_count
(
intel_dp
);
int
max_clock
=
intel_dp_max_link_bw
(
intel_dp
)
==
DP_LINK_BW_2_7
?
1
:
0
;
int
max_clock
=
intel_dp_max_link_bw
(
intel_dp
)
==
DP_LINK_BW_2_7
?
1
:
0
;
static
int
bws
[
2
]
=
{
DP_LINK_BW_1_62
,
DP_LINK_BW_2_7
};
static
int
bws
[
2
]
=
{
DP_LINK_BW_1_62
,
DP_LINK_BW_2_7
};
if
(
is_edp
(
intel_dp
)
&&
dev_priv
->
panel_fixed_mode
)
{
if
(
is_edp
(
intel_dp
)
&&
intel_dp
->
panel_fixed_mode
)
{
intel_fixed_panel_mode
(
dev_priv
->
panel_fixed_mode
,
adjusted_mode
);
intel_fixed_panel_mode
(
intel_dp
->
panel_fixed_mode
,
adjusted_mode
);
intel_pch_panel_fitting
(
dev
,
DRM_MODE_SCALE_FULLSCREEN
,
intel_pch_panel_fitting
(
dev
,
DRM_MODE_SCALE_FULLSCREEN
,
mode
,
adjusted_mode
);
mode
,
adjusted_mode
);
/*
/*
* the mode->clock is used to calculate the Data&Link M/N
* the mode->clock is used to calculate the Data&Link M/N
* of the pipe. For the eDP the fixed clock should be used.
* of the pipe. For the eDP the fixed clock should be used.
*/
*/
mode
->
clock
=
dev_priv
->
panel_fixed_mode
->
clock
;
mode
->
clock
=
intel_dp
->
panel_fixed_mode
->
clock
;
}
}
for
(
lane_count
=
1
;
lane_count
<=
max_lane_count
;
lane_count
<<=
1
)
{
for
(
lane_count
=
1
;
lane_count
<=
max_lane_count
;
lane_count
<<=
1
)
{
...
@@ -740,6 +790,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
...
@@ -740,6 +790,9 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
}
}
}
}
static
void
ironlake_edp_pll_on
(
struct
drm_encoder
*
encoder
);
static
void
ironlake_edp_pll_off
(
struct
drm_encoder
*
encoder
);
static
void
static
void
intel_dp_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
mode
,
intel_dp_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
struct
drm_display_mode
*
adjusted_mode
)
...
@@ -749,6 +802,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
...
@@ -749,6 +802,14 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct
drm_crtc
*
crtc
=
intel_dp
->
base
.
base
.
crtc
;
struct
drm_crtc
*
crtc
=
intel_dp
->
base
.
base
.
crtc
;
struct
intel_crtc
*
intel_crtc
=
to_intel_crtc
(
crtc
);
struct
intel_crtc
*
intel_crtc
=
to_intel_crtc
(
crtc
);
/* Turn on the eDP PLL if needed */
if
(
is_edp
(
intel_dp
))
{
if
(
!
is_pch_edp
(
intel_dp
))
ironlake_edp_pll_on
(
encoder
);
else
ironlake_edp_pll_off
(
encoder
);
}
intel_dp
->
DP
=
DP_VOLTAGE_0_4
|
DP_PRE_EMPHASIS_0
;
intel_dp
->
DP
=
DP_VOLTAGE_0_4
|
DP_PRE_EMPHASIS_0
;
intel_dp
->
DP
|=
intel_dp
->
color_range
;
intel_dp
->
DP
|=
intel_dp
->
color_range
;
...
@@ -808,58 +869,150 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
...
@@ -808,58 +869,150 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
}
}
}
}
static
void
ironlake_wait_panel_off
(
struct
intel_dp
*
intel_dp
)
{
unsigned
long
off_time
;
unsigned
long
delay
;
DRM_DEBUG_KMS
(
"Wait for panel power off time
\n
"
);
if
(
ironlake_edp_have_panel_power
(
intel_dp
)
||
ironlake_edp_have_panel_vdd
(
intel_dp
))
{
DRM_DEBUG_KMS
(
"Panel still on, no delay needed
\n
"
);
return
;
}
off_time
=
intel_dp
->
panel_off_jiffies
+
msecs_to_jiffies
(
intel_dp
->
panel_power_down_delay
);
if
(
time_after
(
jiffies
,
off_time
))
{
DRM_DEBUG_KMS
(
"Time already passed"
);
return
;
}
delay
=
jiffies_to_msecs
(
off_time
-
jiffies
);
if
(
delay
>
intel_dp
->
panel_power_down_delay
)
delay
=
intel_dp
->
panel_power_down_delay
;
DRM_DEBUG_KMS
(
"Waiting an additional %ld ms
\n
"
,
delay
);
msleep
(
delay
);
}
static
void
ironlake_edp_panel_vdd_on
(
struct
intel_dp
*
intel_dp
)
static
void
ironlake_edp_panel_vdd_on
(
struct
intel_dp
*
intel_dp
)
{
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
u32
pp
;
u32
pp
;
/*
if
(
!
is_edp
(
intel_dp
))
* If the panel wasn't on, make sure there's not a currently
return
;
* active PP sequence before enabling AUX VDD.
DRM_DEBUG_KMS
(
"Turn eDP VDD on
\n
"
);
*/
if
(
!
(
I915_READ
(
PCH_PP_STATUS
)
&
PP_ON
))
msleep
(
dev_priv
->
panel_t3
);
WARN
(
intel_dp
->
want_panel_vdd
,
"eDP VDD already requested on
\n
"
);
intel_dp
->
want_panel_vdd
=
true
;
if
(
ironlake_edp_have_panel_vdd
(
intel_dp
))
{
DRM_DEBUG_KMS
(
"eDP VDD already on
\n
"
);
return
;
}
ironlake_wait_panel_off
(
intel_dp
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
&=
~
PANEL_UNLOCK_MASK
;
pp
|=
PANEL_UNLOCK_REGS
;
pp
|=
EDP_FORCE_VDD
;
pp
|=
EDP_FORCE_VDD
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
DRM_DEBUG_KMS
(
"PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x
\n
"
,
I915_READ
(
PCH_PP_STATUS
),
I915_READ
(
PCH_PP_CONTROL
));
/*
* If the panel wasn't on, delay before accessing aux channel
*/
if
(
!
ironlake_edp_have_panel_power
(
intel_dp
))
{
DRM_DEBUG_KMS
(
"eDP was not running
\n
"
);
msleep
(
intel_dp
->
panel_power_up_delay
);
}
}
}
static
void
ironlake_
edp_panel_vdd_off
(
struct
intel_dp
*
intel_dp
)
static
void
ironlake_
panel_vdd_off_sync
(
struct
intel_dp
*
intel_dp
)
{
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
u32
pp
;
u32
pp
;
if
(
!
intel_dp
->
want_panel_vdd
&&
ironlake_edp_have_panel_vdd
(
intel_dp
))
{
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
&=
~
PANEL_UNLOCK_MASK
;
pp
|=
PANEL_UNLOCK_REGS
;
pp
&=
~
EDP_FORCE_VDD
;
pp
&=
~
EDP_FORCE_VDD
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
/* Make sure sequencer is idle before allowing subsequent activity */
/* Make sure sequencer is idle before allowing subsequent activity */
msleep
(
dev_priv
->
panel_t12
);
DRM_DEBUG_KMS
(
"PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x
\n
"
,
I915_READ
(
PCH_PP_STATUS
),
I915_READ
(
PCH_PP_CONTROL
));
intel_dp
->
panel_off_jiffies
=
jiffies
;
}
}
static
void
ironlake_panel_vdd_work
(
struct
work_struct
*
__work
)
{
struct
intel_dp
*
intel_dp
=
container_of
(
to_delayed_work
(
__work
),
struct
intel_dp
,
panel_vdd_work
);
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
mutex_lock
(
&
dev
->
struct_mutex
);
ironlake_panel_vdd_off_sync
(
intel_dp
);
mutex_unlock
(
&
dev
->
struct_mutex
);
}
static
void
ironlake_edp_panel_vdd_off
(
struct
intel_dp
*
intel_dp
,
bool
sync
)
{
if
(
!
is_edp
(
intel_dp
))
return
;
DRM_DEBUG_KMS
(
"Turn eDP VDD off %d
\n
"
,
intel_dp
->
want_panel_vdd
);
WARN
(
!
intel_dp
->
want_panel_vdd
,
"eDP VDD not forced on"
);
intel_dp
->
want_panel_vdd
=
false
;
if
(
sync
)
{
ironlake_panel_vdd_off_sync
(
intel_dp
);
}
else
{
/*
* Queue the timer to fire a long
* time from now (relative to the power down delay)
* to keep the panel power up across a sequence of operations
*/
schedule_delayed_work
(
&
intel_dp
->
panel_vdd_work
,
msecs_to_jiffies
(
intel_dp
->
panel_power_cycle_delay
*
5
));
}
}
}
/* Returns true if the panel was already on when called */
/* Returns true if the panel was already on when called */
static
bool
ironlake_edp_panel_on
(
struct
intel_dp
*
intel_dp
)
static
void
ironlake_edp_panel_on
(
struct
intel_dp
*
intel_dp
)
{
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
u32
pp
,
idle_on_mask
=
PP_ON
|
PP_SEQUENCE_STATE_ON_IDLE
;
u32
pp
,
idle_on_mask
=
PP_ON
|
PP_SEQUENCE_STATE_ON_IDLE
;
if
(
I915_READ
(
PCH_PP_STATUS
)
&
PP_ON
)
if
(
!
is_edp
(
intel_dp
))
return
true
;
return
;
if
(
ironlake_edp_have_panel_power
(
intel_dp
))
return
;
ironlake_wait_panel_off
(
intel_dp
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
&=
~
PANEL_UNLOCK_MASK
;
pp
|=
PANEL_UNLOCK_REGS
;
if
(
IS_GEN5
(
dev
))
{
/* ILK workaround: disable reset around power sequence */
/* ILK workaround: disable reset around power sequence */
pp
&=
~
PANEL_POWER_RESET
;
pp
&=
~
PANEL_POWER_RESET
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
}
pp
|=
P
ANEL_UNLOCK_REGS
|
P
OWER_TARGET_ON
;
pp
|=
POWER_TARGET_ON
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
...
@@ -868,29 +1021,44 @@ static bool ironlake_edp_panel_on(struct intel_dp *intel_dp)
...
@@ -868,29 +1021,44 @@ static bool ironlake_edp_panel_on(struct intel_dp *intel_dp)
DRM_ERROR
(
"panel on wait timed out: 0x%08x
\n
"
,
DRM_ERROR
(
"panel on wait timed out: 0x%08x
\n
"
,
I915_READ
(
PCH_PP_STATUS
));
I915_READ
(
PCH_PP_STATUS
));
if
(
IS_GEN5
(
dev
))
{
pp
|=
PANEL_POWER_RESET
;
/* restore panel reset bit */
pp
|=
PANEL_POWER_RESET
;
/* restore panel reset bit */
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
}
return
false
;
}
}
static
void
ironlake_edp_panel_off
(
struct
drm_
device
*
dev
)
static
void
ironlake_edp_panel_off
(
struct
drm_
encoder
*
encoder
)
{
{
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
u32
pp
,
idle_off_mask
=
PP_ON
|
PP_SEQUENCE_MASK
|
u32
pp
,
idle_off_mask
=
PP_ON
|
PP_SEQUENCE_MASK
|
PP_CYCLE_DELAY_ACTIVE
|
PP_SEQUENCE_STATE_MASK
;
PP_CYCLE_DELAY_ACTIVE
|
PP_SEQUENCE_STATE_MASK
;
if
(
!
is_edp
(
intel_dp
))
return
;
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
&=
~
PANEL_UNLOCK_MASK
;
pp
|=
PANEL_UNLOCK_REGS
;
if
(
IS_GEN5
(
dev
))
{
/* ILK workaround: disable reset around power sequence */
/* ILK workaround: disable reset around power sequence */
pp
&=
~
PANEL_POWER_RESET
;
pp
&=
~
PANEL_POWER_RESET
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
}
intel_dp
->
panel_off_jiffies
=
jiffies
;
if
(
IS_GEN5
(
dev
))
{
pp
&=
~
POWER_TARGET_ON
;
pp
&=
~
POWER_TARGET_ON
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
pp
&=
~
POWER_TARGET_ON
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
msleep
(
intel_dp
->
panel_power_cycle_delay
);
if
(
wait_for
((
I915_READ
(
PCH_PP_STATUS
)
&
idle_off_mask
)
==
0
,
5000
))
if
(
wait_for
((
I915_READ
(
PCH_PP_STATUS
)
&
idle_off_mask
)
==
0
,
5000
))
DRM_ERROR
(
"panel off wait timed out: 0x%08x
\n
"
,
DRM_ERROR
(
"panel off wait timed out: 0x%08x
\n
"
,
...
@@ -899,13 +1067,18 @@ static void ironlake_edp_panel_off(struct drm_device *dev)
...
@@ -899,13 +1067,18 @@ static void ironlake_edp_panel_off(struct drm_device *dev)
pp
|=
PANEL_POWER_RESET
;
/* restore panel reset bit */
pp
|=
PANEL_POWER_RESET
;
/* restore panel reset bit */
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
POSTING_READ
(
PCH_PP_CONTROL
);
}
}
}
static
void
ironlake_edp_backlight_on
(
struct
drm_device
*
dev
)
static
void
ironlake_edp_backlight_on
(
struct
intel_dp
*
intel_dp
)
{
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
u32
pp
;
u32
pp
;
if
(
!
is_edp
(
intel_dp
))
return
;
DRM_DEBUG_KMS
(
"
\n
"
);
DRM_DEBUG_KMS
(
"
\n
"
);
/*
/*
* If we enable the backlight right away following a panel power
* If we enable the backlight right away following a panel power
...
@@ -913,21 +1086,32 @@ static void ironlake_edp_backlight_on(struct drm_device *dev)
...
@@ -913,21 +1086,32 @@ static void ironlake_edp_backlight_on(struct drm_device *dev)
* link. So delay a bit to make sure the image is solid before
* link. So delay a bit to make sure the image is solid before
* allowing it to appear.
* allowing it to appear.
*/
*/
msleep
(
300
);
msleep
(
intel_dp
->
backlight_on_delay
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
&=
~
PANEL_UNLOCK_MASK
;
pp
|=
PANEL_UNLOCK_REGS
;
pp
|=
EDP_BLC_ENABLE
;
pp
|=
EDP_BLC_ENABLE
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
}
}
static
void
ironlake_edp_backlight_off
(
struct
drm_device
*
dev
)
static
void
ironlake_edp_backlight_off
(
struct
intel_dp
*
intel_dp
)
{
{
struct
drm_device
*
dev
=
intel_dp
->
base
.
base
.
dev
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
struct
drm_i915_private
*
dev_priv
=
dev
->
dev_private
;
u32
pp
;
u32
pp
;
if
(
!
is_edp
(
intel_dp
))
return
;
DRM_DEBUG_KMS
(
"
\n
"
);
DRM_DEBUG_KMS
(
"
\n
"
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
=
I915_READ
(
PCH_PP_CONTROL
);
pp
&=
~
PANEL_UNLOCK_MASK
;
pp
|=
PANEL_UNLOCK_REGS
;
pp
&=
~
EDP_BLC_ENABLE
;
pp
&=
~
EDP_BLC_ENABLE
;
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
I915_WRITE
(
PCH_PP_CONTROL
,
pp
);
POSTING_READ
(
PCH_PP_CONTROL
);
msleep
(
intel_dp
->
backlight_off_delay
);
}
}
static
void
ironlake_edp_pll_on
(
struct
drm_encoder
*
encoder
)
static
void
ironlake_edp_pll_on
(
struct
drm_encoder
*
encoder
)
...
@@ -990,41 +1174,32 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
...
@@ -990,41 +1174,32 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
static
void
intel_dp_prepare
(
struct
drm_encoder
*
encoder
)
static
void
intel_dp_prepare
(
struct
drm_encoder
*
encoder
)
{
{
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
struct
drm_device
*
dev
=
encoder
->
dev
;
/* Wake up the sink first */
/* Wake up the sink first */
ironlake_edp_panel_vdd_on
(
intel_dp
);
intel_dp_sink_dpms
(
intel_dp
,
DRM_MODE_DPMS_ON
);
intel_dp_sink_dpms
(
intel_dp
,
DRM_MODE_DPMS_ON
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
if
(
is_edp
(
intel_dp
))
{
/* Make sure the panel is off before trying to
ironlake_edp_backlight_off
(
dev
);
* change the mode
ironlake_edp_panel_off
(
dev
);
*/
if
(
!
is_pch_edp
(
intel_dp
))
ironlake_edp_backlight_off
(
intel_dp
);
ironlake_edp_pll_on
(
encoder
);
else
ironlake_edp_pll_off
(
encoder
);
}
intel_dp_link_down
(
intel_dp
);
intel_dp_link_down
(
intel_dp
);
ironlake_edp_panel_off
(
encoder
);
}
}
static
void
intel_dp_commit
(
struct
drm_encoder
*
encoder
)
static
void
intel_dp_commit
(
struct
drm_encoder
*
encoder
)
{
{
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
struct
intel_dp
*
intel_dp
=
enc_to_intel_dp
(
encoder
);
struct
drm_device
*
dev
=
encoder
->
dev
;
if
(
is_edp
(
intel_dp
))
ironlake_edp_panel_vdd_on
(
intel_dp
);
ironlake_edp_panel_vdd_on
(
intel_dp
);
intel_dp_sink_dpms
(
intel_dp
,
DRM_MODE_DPMS_ON
);
intel_dp_start_link_train
(
intel_dp
);
intel_dp_start_link_train
(
intel_dp
);
if
(
is_edp
(
intel_dp
))
{
ironlake_edp_panel_on
(
intel_dp
);
ironlake_edp_panel_on
(
intel_dp
);
ironlake_edp_panel_vdd_off
(
intel_dp
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
true
);
}
intel_dp_complete_link_train
(
intel_dp
);
intel_dp_complete_link_train
(
intel_dp
);
ironlake_edp_backlight_on
(
intel_dp
);
if
(
is_edp
(
intel_dp
))
ironlake_edp_backlight_on
(
dev
);
intel_dp
->
dpms_mode
=
DRM_MODE_DPMS_ON
;
intel_dp
->
dpms_mode
=
DRM_MODE_DPMS_ON
;
}
}
...
@@ -1038,28 +1213,27 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
...
@@ -1038,28 +1213,27 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
uint32_t
dp_reg
=
I915_READ
(
intel_dp
->
output_reg
);
uint32_t
dp_reg
=
I915_READ
(
intel_dp
->
output_reg
);
if
(
mode
!=
DRM_MODE_DPMS_ON
)
{
if
(
mode
!=
DRM_MODE_DPMS_ON
)
{
ironlake_edp_panel_vdd_on
(
intel_dp
);
if
(
is_edp
(
intel_dp
))
if
(
is_edp
(
intel_dp
))
ironlake_edp_backlight_off
(
dev
);
ironlake_edp_backlight_off
(
intel_dp
);
intel_dp_sink_dpms
(
intel_dp
,
mode
);
intel_dp_sink_dpms
(
intel_dp
,
mode
);
intel_dp_link_down
(
intel_dp
);
intel_dp_link_down
(
intel_dp
);
if
(
is_edp
(
intel_dp
))
ironlake_edp_panel_off
(
encoder
);
ironlake_edp_panel_off
(
dev
);
if
(
is_edp
(
intel_dp
)
&&
!
is_pch_edp
(
intel_dp
))
if
(
is_edp
(
intel_dp
)
&&
!
is_pch_edp
(
intel_dp
))
ironlake_edp_pll_off
(
encoder
);
ironlake_edp_pll_off
(
encoder
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
}
else
{
}
else
{
if
(
is_edp
(
intel_dp
))
ironlake_edp_panel_vdd_on
(
intel_dp
);
ironlake_edp_panel_vdd_on
(
intel_dp
);
intel_dp_sink_dpms
(
intel_dp
,
mode
);
intel_dp_sink_dpms
(
intel_dp
,
mode
);
if
(
!
(
dp_reg
&
DP_PORT_EN
))
{
if
(
!
(
dp_reg
&
DP_PORT_EN
))
{
intel_dp_start_link_train
(
intel_dp
);
intel_dp_start_link_train
(
intel_dp
);
if
(
is_edp
(
intel_dp
))
{
ironlake_edp_panel_on
(
intel_dp
);
ironlake_edp_panel_on
(
intel_dp
);
ironlake_edp_panel_vdd_off
(
intel_dp
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
true
);
}
intel_dp_complete_link_train
(
intel_dp
);
intel_dp_complete_link_train
(
intel_dp
);
}
ironlake_edp_backlight_on
(
intel_dp
);
if
(
is_edp
(
intel_dp
))
}
else
ironlake_edp_backlight_on
(
dev
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
ironlake_edp_backlight_on
(
intel_dp
);
}
}
intel_dp
->
dpms_mode
=
mode
;
intel_dp
->
dpms_mode
=
mode
;
}
}
...
@@ -1582,6 +1756,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
...
@@ -1582,6 +1756,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
I915_WRITE
(
intel_dp
->
output_reg
,
DP
&
~
DP_PORT_EN
);
I915_WRITE
(
intel_dp
->
output_reg
,
DP
&
~
DP_PORT_EN
);
POSTING_READ
(
intel_dp
->
output_reg
);
POSTING_READ
(
intel_dp
->
output_reg
);
msleep
(
intel_dp
->
panel_power_down_delay
);
}
}
static
bool
static
bool
...
@@ -1687,6 +1862,31 @@ g4x_dp_detect(struct intel_dp *intel_dp)
...
@@ -1687,6 +1862,31 @@ g4x_dp_detect(struct intel_dp *intel_dp)
return
intel_dp_detect_dpcd
(
intel_dp
);
return
intel_dp_detect_dpcd
(
intel_dp
);
}
}
static
struct
edid
*
intel_dp_get_edid
(
struct
drm_connector
*
connector
,
struct
i2c_adapter
*
adapter
)
{
struct
intel_dp
*
intel_dp
=
intel_attached_dp
(
connector
);
struct
edid
*
edid
;
ironlake_edp_panel_vdd_on
(
intel_dp
);
edid
=
drm_get_edid
(
connector
,
adapter
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
return
edid
;
}
static
int
intel_dp_get_edid_modes
(
struct
drm_connector
*
connector
,
struct
i2c_adapter
*
adapter
)
{
struct
intel_dp
*
intel_dp
=
intel_attached_dp
(
connector
);
int
ret
;
ironlake_edp_panel_vdd_on
(
intel_dp
);
ret
=
intel_ddc_get_modes
(
connector
,
adapter
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
return
ret
;
}
/**
/**
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
* Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
*
*
...
@@ -1719,7 +1919,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
...
@@ -1719,7 +1919,7 @@ intel_dp_detect(struct drm_connector *connector, bool force)
if
(
intel_dp
->
force_audio
)
{
if
(
intel_dp
->
force_audio
)
{
intel_dp
->
has_audio
=
intel_dp
->
force_audio
>
0
;
intel_dp
->
has_audio
=
intel_dp
->
force_audio
>
0
;
}
else
{
}
else
{
edid
=
drm
_get_edid
(
connector
,
&
intel_dp
->
adapter
);
edid
=
intel_dp
_get_edid
(
connector
,
&
intel_dp
->
adapter
);
if
(
edid
)
{
if
(
edid
)
{
intel_dp
->
has_audio
=
drm_detect_monitor_audio
(
edid
);
intel_dp
->
has_audio
=
drm_detect_monitor_audio
(
edid
);
connector
->
display_info
.
raw_edid
=
NULL
;
connector
->
display_info
.
raw_edid
=
NULL
;
...
@@ -1740,28 +1940,36 @@ static int intel_dp_get_modes(struct drm_connector *connector)
...
@@ -1740,28 +1940,36 @@ static int intel_dp_get_modes(struct drm_connector *connector)
/* We should parse the EDID data and find out if it has an audio sink
/* We should parse the EDID data and find out if it has an audio sink
*/
*/
ret
=
intel_d
dc_get
_modes
(
connector
,
&
intel_dp
->
adapter
);
ret
=
intel_d
p_get_edid
_modes
(
connector
,
&
intel_dp
->
adapter
);
if
(
ret
)
{
if
(
ret
)
{
if
(
is_edp
(
intel_dp
)
&&
!
dev_priv
->
panel_fixed_mode
)
{
if
(
is_edp
(
intel_dp
)
&&
!
intel_dp
->
panel_fixed_mode
)
{
struct
drm_display_mode
*
newmode
;
struct
drm_display_mode
*
newmode
;
list_for_each_entry
(
newmode
,
&
connector
->
probed_modes
,
list_for_each_entry
(
newmode
,
&
connector
->
probed_modes
,
head
)
{
head
)
{
if
(
newmode
->
type
&
DRM_MODE_TYPE_PREFERRED
)
{
if
(
(
newmode
->
type
&
DRM_MODE_TYPE_PREFERRED
)
)
{
dev_priv
->
panel_fixed_mode
=
intel_dp
->
panel_fixed_mode
=
drm_mode_duplicate
(
dev
,
newmode
);
drm_mode_duplicate
(
dev
,
newmode
);
break
;
break
;
}
}
}
}
}
}
return
ret
;
return
ret
;
}
}
/* if eDP has no EDID, try to use fixed panel mode from VBT */
/* if eDP has no EDID, try to use fixed panel mode from VBT */
if
(
is_edp
(
intel_dp
))
{
if
(
is_edp
(
intel_dp
))
{
if
(
dev_priv
->
panel_fixed_mode
!=
NULL
)
{
/* initialize panel mode from VBT if available for eDP */
if
(
intel_dp
->
panel_fixed_mode
==
NULL
&&
dev_priv
->
lfp_lvds_vbt_mode
!=
NULL
)
{
intel_dp
->
panel_fixed_mode
=
drm_mode_duplicate
(
dev
,
dev_priv
->
lfp_lvds_vbt_mode
);
if
(
intel_dp
->
panel_fixed_mode
)
{
intel_dp
->
panel_fixed_mode
->
type
|=
DRM_MODE_TYPE_PREFERRED
;
}
}
if
(
intel_dp
->
panel_fixed_mode
)
{
struct
drm_display_mode
*
mode
;
struct
drm_display_mode
*
mode
;
mode
=
drm_mode_duplicate
(
dev
,
dev_priv
->
panel_fixed_mode
);
mode
=
drm_mode_duplicate
(
dev
,
intel_dp
->
panel_fixed_mode
);
drm_mode_probed_add
(
connector
,
mode
);
drm_mode_probed_add
(
connector
,
mode
);
return
1
;
return
1
;
}
}
...
@@ -1776,7 +1984,7 @@ intel_dp_detect_audio(struct drm_connector *connector)
...
@@ -1776,7 +1984,7 @@ intel_dp_detect_audio(struct drm_connector *connector)
struct
edid
*
edid
;
struct
edid
*
edid
;
bool
has_audio
=
false
;
bool
has_audio
=
false
;
edid
=
drm
_get_edid
(
connector
,
&
intel_dp
->
adapter
);
edid
=
intel_dp
_get_edid
(
connector
,
&
intel_dp
->
adapter
);
if
(
edid
)
{
if
(
edid
)
{
has_audio
=
drm_detect_monitor_audio
(
edid
);
has_audio
=
drm_detect_monitor_audio
(
edid
);
...
@@ -1861,6 +2069,10 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
...
@@ -1861,6 +2069,10 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
i2c_del_adapter
(
&
intel_dp
->
adapter
);
i2c_del_adapter
(
&
intel_dp
->
adapter
);
drm_encoder_cleanup
(
encoder
);
drm_encoder_cleanup
(
encoder
);
if
(
is_edp
(
intel_dp
))
{
cancel_delayed_work_sync
(
&
intel_dp
->
panel_vdd_work
);
ironlake_panel_vdd_off_sync
(
intel_dp
);
}
kfree
(
intel_dp
);
kfree
(
intel_dp
);
}
}
...
@@ -1997,8 +2209,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
...
@@ -1997,8 +2209,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
else
if
(
output_reg
==
DP_D
||
output_reg
==
PCH_DP_D
)
else
if
(
output_reg
==
DP_D
||
output_reg
==
PCH_DP_D
)
intel_encoder
->
clone_mask
=
(
1
<<
INTEL_DP_D_CLONE_BIT
);
intel_encoder
->
clone_mask
=
(
1
<<
INTEL_DP_D_CLONE_BIT
);
if
(
is_edp
(
intel_dp
))
if
(
is_edp
(
intel_dp
))
{
intel_encoder
->
clone_mask
=
(
1
<<
INTEL_EDP_CLONE_BIT
);
intel_encoder
->
clone_mask
=
(
1
<<
INTEL_EDP_CLONE_BIT
);
INIT_DELAYED_WORK
(
&
intel_dp
->
panel_vdd_work
,
ironlake_panel_vdd_work
);
}
intel_encoder
->
crtc_mask
=
(
1
<<
0
)
|
(
1
<<
1
);
intel_encoder
->
crtc_mask
=
(
1
<<
0
)
|
(
1
<<
1
);
connector
->
interlace_allowed
=
true
;
connector
->
interlace_allowed
=
true
;
...
@@ -2036,25 +2251,60 @@ intel_dp_init(struct drm_device *dev, int output_reg)
...
@@ -2036,25 +2251,60 @@ intel_dp_init(struct drm_device *dev, int output_reg)
break
;
break
;
}
}
intel_dp_i2c_init
(
intel_dp
,
intel_connector
,
name
);
/* Cache some DPCD data in the eDP case */
/* Cache some DPCD data in the eDP case */
if
(
is_edp
(
intel_dp
))
{
if
(
is_edp
(
intel_dp
))
{
bool
ret
;
bool
ret
;
u32
pp_on
,
pp_div
;
struct
edp_power_seq
cur
,
vbt
;
u32
pp_on
,
pp_off
,
pp_div
;
pp_on
=
I915_READ
(
PCH_PP_ON_DELAYS
);
pp_on
=
I915_READ
(
PCH_PP_ON_DELAYS
);
pp_off
=
I915_READ
(
PCH_PP_OFF_DELAYS
);
pp_div
=
I915_READ
(
PCH_PP_DIVISOR
);
pp_div
=
I915_READ
(
PCH_PP_DIVISOR
);
/* Get T3 & T12 values (note: VESA not bspec terminology) */
/* Pull timing values out of registers */
dev_priv
->
panel_t3
=
(
pp_on
&
0x1fff0000
)
>>
16
;
cur
.
t1_t3
=
(
pp_on
&
PANEL_POWER_UP_DELAY_MASK
)
>>
dev_priv
->
panel_t3
/=
10
;
/* t3 in 100us units */
PANEL_POWER_UP_DELAY_SHIFT
;
dev_priv
->
panel_t12
=
pp_div
&
0xf
;
dev_priv
->
panel_t12
*=
100
;
/* t12 in 100ms units */
cur
.
t8
=
(
pp_on
&
PANEL_LIGHT_ON_DELAY_MASK
)
>>
PANEL_LIGHT_ON_DELAY_SHIFT
;
cur
.
t9
=
(
pp_off
&
PANEL_LIGHT_OFF_DELAY_MASK
)
>>
PANEL_LIGHT_OFF_DELAY_SHIFT
;
cur
.
t10
=
(
pp_off
&
PANEL_POWER_DOWN_DELAY_MASK
)
>>
PANEL_POWER_DOWN_DELAY_SHIFT
;
cur
.
t11_t12
=
((
pp_div
&
PANEL_POWER_CYCLE_DELAY_MASK
)
>>
PANEL_POWER_CYCLE_DELAY_SHIFT
)
*
1000
;
DRM_DEBUG_KMS
(
"cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d
\n
"
,
cur
.
t1_t3
,
cur
.
t8
,
cur
.
t9
,
cur
.
t10
,
cur
.
t11_t12
);
vbt
=
dev_priv
->
edp
.
pps
;
DRM_DEBUG_KMS
(
"vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d
\n
"
,
vbt
.
t1_t3
,
vbt
.
t8
,
vbt
.
t9
,
vbt
.
t10
,
vbt
.
t11_t12
);
#define get_delay(field) ((max(cur.field, vbt.field) + 9) / 10)
intel_dp
->
panel_power_up_delay
=
get_delay
(
t1_t3
);
intel_dp
->
backlight_on_delay
=
get_delay
(
t8
);
intel_dp
->
backlight_off_delay
=
get_delay
(
t9
);
intel_dp
->
panel_power_down_delay
=
get_delay
(
t10
);
intel_dp
->
panel_power_cycle_delay
=
get_delay
(
t11_t12
);
DRM_DEBUG_KMS
(
"panel power up delay %d, power down delay %d, power cycle delay %d
\n
"
,
intel_dp
->
panel_power_up_delay
,
intel_dp
->
panel_power_down_delay
,
intel_dp
->
panel_power_cycle_delay
);
DRM_DEBUG_KMS
(
"backlight on delay %d, off delay %d
\n
"
,
intel_dp
->
backlight_on_delay
,
intel_dp
->
backlight_off_delay
);
intel_dp
->
panel_off_jiffies
=
jiffies
-
intel_dp
->
panel_power_down_delay
;
ironlake_edp_panel_vdd_on
(
intel_dp
);
ironlake_edp_panel_vdd_on
(
intel_dp
);
ret
=
intel_dp_get_dpcd
(
intel_dp
);
ret
=
intel_dp_get_dpcd
(
intel_dp
);
ironlake_edp_panel_vdd_off
(
intel_dp
);
ironlake_edp_panel_vdd_off
(
intel_dp
,
false
);
if
(
ret
)
{
if
(
ret
)
{
if
(
intel_dp
->
dpcd
[
DP_DPCD_REV
]
>=
0x11
)
if
(
intel_dp
->
dpcd
[
DP_DPCD_REV
]
>=
0x11
)
dev_priv
->
no_aux_handshake
=
dev_priv
->
no_aux_handshake
=
...
@@ -2069,18 +2319,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
...
@@ -2069,18 +2319,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
}
}
}
}
intel_dp_i2c_init
(
intel_dp
,
intel_connector
,
name
);
intel_encoder
->
hot_plug
=
intel_dp_hot_plug
;
intel_encoder
->
hot_plug
=
intel_dp_hot_plug
;
if
(
is_edp
(
intel_dp
))
{
if
(
is_edp
(
intel_dp
))
{
/* initialize panel mode from VBT if available for eDP */
if
(
dev_priv
->
lfp_lvds_vbt_mode
)
{
dev_priv
->
panel_fixed_mode
=
drm_mode_duplicate
(
dev
,
dev_priv
->
lfp_lvds_vbt_mode
);
if
(
dev_priv
->
panel_fixed_mode
)
{
dev_priv
->
panel_fixed_mode
->
type
|=
DRM_MODE_TYPE_PREFERRED
;
}
}
dev_priv
->
int_edp_connector
=
connector
;
dev_priv
->
int_edp_connector
=
connector
;
intel_panel_setup_backlight
(
dev
);
intel_panel_setup_backlight
(
dev
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录