Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
eb6313ad
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 3 年多
通知
13
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看板
提交
eb6313ad
编写于
2月 11, 2013
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nv50: initial kms support for off-chip TMDS/DP encoders
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
476e84e1
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
202 addition
and
18 deletion
+202
-18
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bios.c
+4
-1
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_display.c
+198
-17
未找到文件。
drivers/gpu/drm/nouveau/nouveau_bios.c
浏览文件 @
eb6313ad
...
...
@@ -1469,6 +1469,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
}
case
DCB_OUTPUT_DP
:
entry
->
dpconf
.
sor
.
link
=
(
conf
&
0x00000030
)
>>
4
;
entry
->
extdev
=
(
conf
&
0x0000ff00
)
>>
8
;
switch
((
conf
&
0x00e00000
)
>>
21
)
{
case
0
:
entry
->
dpconf
.
link_bw
=
162000
;
...
...
@@ -1490,8 +1491,10 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
}
break
;
case
DCB_OUTPUT_TMDS
:
if
(
dcb
->
version
>=
0x40
)
if
(
dcb
->
version
>=
0x40
)
{
entry
->
tmdsconf
.
sor
.
link
=
(
conf
&
0x00000030
)
>>
4
;
entry
->
extdev
=
(
conf
&
0x0000ff00
)
>>
8
;
}
else
if
(
dcb
->
version
>=
0x30
)
entry
->
tmdsconf
.
slave_addr
=
(
conf
&
0x00000700
)
>>
8
;
else
if
(
dcb
->
version
>=
0x22
)
...
...
drivers/gpu/drm/nouveau/nv50_display.c
浏览文件 @
eb6313ad
...
...
@@ -1922,6 +1922,184 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
return
0
;
}
/******************************************************************************
* PIOR
*****************************************************************************/
static
void
nv50_pior_dpms
(
struct
drm_encoder
*
encoder
,
int
mode
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nv50_disp
*
disp
=
nv50_disp
(
encoder
->
dev
);
u32
mthd
=
(
nv_encoder
->
dcb
->
type
<<
12
)
|
nv_encoder
->
or
;
u32
ctrl
=
(
mode
==
DRM_MODE_DPMS_ON
);
nv_call
(
disp
->
core
,
NV50_DISP_PIOR_PWR
+
mthd
,
ctrl
);
}
static
bool
nv50_pior_mode_fixup
(
struct
drm_encoder
*
encoder
,
const
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_connector
*
nv_connector
;
nv_connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
nv_connector
&&
nv_connector
->
native_mode
)
{
if
(
nv_connector
->
scaling_mode
!=
DRM_MODE_SCALE_NONE
)
{
int
id
=
adjusted_mode
->
base
.
id
;
*
adjusted_mode
=
*
nv_connector
->
native_mode
;
adjusted_mode
->
base
.
id
=
id
;
}
}
adjusted_mode
->
clock
*=
2
;
return
true
;
}
static
void
nv50_pior_commit
(
struct
drm_encoder
*
encoder
)
{
}
static
void
nv50_pior_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
{
struct
nv50_mast
*
mast
=
nv50_mast
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
encoder
->
crtc
);
struct
nouveau_connector
*
nv_connector
;
u8
owner
=
1
<<
nv_crtc
->
index
;
u8
proto
,
depth
;
u32
*
push
;
nv_connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
switch
(
nv_connector
->
base
.
display_info
.
bpc
)
{
case
10
:
depth
=
0x6
;
break
;
case
8
:
depth
=
0x5
;
break
;
case
6
:
depth
=
0x2
;
break
;
default:
depth
=
0x0
;
break
;
}
switch
(
nv_encoder
->
dcb
->
type
)
{
case
DCB_OUTPUT_TMDS
:
case
DCB_OUTPUT_DP
:
proto
=
0x0
;
break
;
default:
BUG_ON
(
1
);
break
;
}
nv50_pior_dpms
(
encoder
,
DRM_MODE_DPMS_ON
);
push
=
evo_wait
(
mast
,
8
);
if
(
push
)
{
if
(
nv50_vers
(
mast
)
<
NVD0_DISP_MAST_CLASS
)
{
u32
ctrl
=
(
depth
<<
16
)
|
(
proto
<<
8
)
|
owner
;
if
(
mode
->
flags
&
DRM_MODE_FLAG_NHSYNC
)
ctrl
|=
0x00001000
;
if
(
mode
->
flags
&
DRM_MODE_FLAG_NVSYNC
)
ctrl
|=
0x00002000
;
evo_mthd
(
push
,
0x0700
+
(
nv_encoder
->
or
*
0x040
),
1
);
evo_data
(
push
,
ctrl
);
}
evo_kick
(
push
,
mast
);
}
nv_encoder
->
crtc
=
encoder
->
crtc
;
}
static
void
nv50_pior_disconnect
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nv50_mast
*
mast
=
nv50_mast
(
encoder
->
dev
);
const
int
or
=
nv_encoder
->
or
;
u32
*
push
;
if
(
nv_encoder
->
crtc
)
{
nv50_crtc_prepare
(
nv_encoder
->
crtc
);
push
=
evo_wait
(
mast
,
4
);
if
(
push
)
{
if
(
nv50_vers
(
mast
)
<
NVD0_DISP_MAST_CLASS
)
{
evo_mthd
(
push
,
0x0700
+
(
or
*
0x040
),
1
);
evo_data
(
push
,
0x00000000
);
}
evo_mthd
(
push
,
0x0080
,
1
);
evo_data
(
push
,
0x00000000
);
evo_kick
(
push
,
mast
);
}
}
nv_encoder
->
crtc
=
NULL
;
}
static
void
nv50_pior_destroy
(
struct
drm_encoder
*
encoder
)
{
drm_encoder_cleanup
(
encoder
);
kfree
(
encoder
);
}
static
const
struct
drm_encoder_helper_funcs
nv50_pior_hfunc
=
{
.
dpms
=
nv50_pior_dpms
,
.
mode_fixup
=
nv50_pior_mode_fixup
,
.
prepare
=
nv50_pior_disconnect
,
.
commit
=
nv50_pior_commit
,
.
mode_set
=
nv50_pior_mode_set
,
.
disable
=
nv50_pior_disconnect
,
.
get_crtc
=
nv50_display_crtc_get
,
};
static
const
struct
drm_encoder_funcs
nv50_pior_func
=
{
.
destroy
=
nv50_pior_destroy
,
};
static
int
nv50_pior_create
(
struct
drm_connector
*
connector
,
struct
dcb_output
*
dcbe
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
connector
->
dev
);
struct
nouveau_i2c
*
i2c
=
nouveau_i2c
(
drm
->
device
);
struct
nouveau_i2c_port
*
ddc
=
NULL
;
struct
nouveau_encoder
*
nv_encoder
;
struct
drm_encoder
*
encoder
;
int
type
;
switch
(
dcbe
->
type
)
{
case
DCB_OUTPUT_TMDS
:
ddc
=
i2c
->
find_type
(
i2c
,
NV_I2C_TYPE_EXTDDC
(
dcbe
->
extdev
));
type
=
DRM_MODE_ENCODER_TMDS
;
break
;
case
DCB_OUTPUT_DP
:
ddc
=
i2c
->
find_type
(
i2c
,
NV_I2C_TYPE_EXTAUX
(
dcbe
->
extdev
));
type
=
DRM_MODE_ENCODER_TMDS
;
break
;
default:
return
-
ENODEV
;
}
nv_encoder
=
kzalloc
(
sizeof
(
*
nv_encoder
),
GFP_KERNEL
);
if
(
!
nv_encoder
)
return
-
ENOMEM
;
nv_encoder
->
dcb
=
dcbe
;
nv_encoder
->
or
=
ffs
(
dcbe
->
or
)
-
1
;
nv_encoder
->
i2c
=
ddc
;
encoder
=
to_drm_encoder
(
nv_encoder
);
encoder
->
possible_crtcs
=
dcbe
->
heads
;
encoder
->
possible_clones
=
0
;
drm_encoder_init
(
connector
->
dev
,
encoder
,
&
nv50_pior_func
,
type
);
drm_encoder_helper_add
(
encoder
,
&
nv50_pior_hfunc
);
drm_mode_connector_attach_encoder
(
connector
,
encoder
);
return
0
;
}
/******************************************************************************
* Init
*****************************************************************************/
...
...
@@ -2044,25 +2222,28 @@ nv50_display_create(struct drm_device *dev)
if
(
IS_ERR
(
connector
))
continue
;
if
(
dcbe
->
location
!=
DCB_LOC_ON_CHIP
)
{
NV_WARN
(
drm
,
"skipping off-chip encoder %d/%d
\n
"
,
dcbe
->
type
,
ffs
(
dcbe
->
or
)
-
1
);
continue
;
if
(
dcbe
->
location
==
DCB_LOC_ON_CHIP
)
{
switch
(
dcbe
->
type
)
{
case
DCB_OUTPUT_TMDS
:
case
DCB_OUTPUT_LVDS
:
case
DCB_OUTPUT_DP
:
ret
=
nv50_sor_create
(
connector
,
dcbe
);
break
;
case
DCB_OUTPUT_ANALOG
:
ret
=
nv50_dac_create
(
connector
,
dcbe
);
break
;
default:
ret
=
-
ENODEV
;
break
;
}
}
else
{
ret
=
nv50_pior_create
(
connector
,
dcbe
);
}
switch
(
dcbe
->
type
)
{
case
DCB_OUTPUT_TMDS
:
case
DCB_OUTPUT_LVDS
:
case
DCB_OUTPUT_DP
:
nv50_sor_create
(
connector
,
dcbe
);
break
;
case
DCB_OUTPUT_ANALOG
:
nv50_dac_create
(
connector
,
dcbe
);
break
;
default:
NV_WARN
(
drm
,
"skipping unsupported encoder %d/%d
\n
"
,
dcbe
->
type
,
ffs
(
dcbe
->
or
)
-
1
);
continue
;
if
(
ret
)
{
NV_WARN
(
drm
,
"failed to create encoder %d/%d/%d: %d
\n
"
,
dcbe
->
location
,
dcbe
->
type
,
ffs
(
dcbe
->
or
)
-
1
,
ret
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录