Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
4f6029da
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
158
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4f6029da
编写于
11月 16, 2012
作者:
B
Ben Skeggs
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
drm/nv50-nvc0: switch to common disp impl, removing previous version
Signed-off-by:
N
Ben Skeggs
<
bskeggs@redhat.com
>
上级
f9887d09
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
31 addition
and
2700 deletion
+31
-2700
drivers/gpu/drm/nouveau/Makefile
drivers/gpu/drm/nouveau/Makefile
+2
-4
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/nouveau/nouveau_connector.h
+16
-0
drivers/gpu/drm/nouveau/nouveau_crtc.h
drivers/gpu/drm/nouveau/nouveau_crtc.h
+0
-3
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.c
+6
-12
drivers/gpu/drm/nouveau/nouveau_hdmi.c
drivers/gpu/drm/nouveau/nouveau_hdmi.c
+0
-123
drivers/gpu/drm/nouveau/nv50_crtc.c
drivers/gpu/drm/nouveau/nv50_crtc.c
+0
-753
drivers/gpu/drm/nouveau/nv50_cursor.c
drivers/gpu/drm/nouveau/nv50_cursor.c
+0
-132
drivers/gpu/drm/nouveau/nv50_dac.c
drivers/gpu/drm/nouveau/nv50_dac.c
+0
-276
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_display.c
+0
-462
drivers/gpu/drm/nouveau/nv50_display.h
drivers/gpu/drm/nouveau/nv50_display.h
+0
-60
drivers/gpu/drm/nouveau/nv50_evo.c
drivers/gpu/drm/nouveau/nv50_evo.c
+0
-396
drivers/gpu/drm/nouveau/nv50_evo.h
drivers/gpu/drm/nouveau/nv50_evo.h
+0
-120
drivers/gpu/drm/nouveau/nv50_fence.c
drivers/gpu/drm/nouveau/nv50_fence.c
+1
-1
drivers/gpu/drm/nouveau/nv50_pm.c
drivers/gpu/drm/nouveau/nv50_pm.c
+1
-1
drivers/gpu/drm/nouveau/nv50_sor.c
drivers/gpu/drm/nouveau/nv50_sor.c
+0
-339
drivers/gpu/drm/nouveau/nv84_fence.c
drivers/gpu/drm/nouveau/nv84_fence.c
+1
-1
drivers/gpu/drm/nouveau/nvc0_fence.c
drivers/gpu/drm/nouveau/nvc0_fence.c
+4
-17
未找到文件。
drivers/gpu/drm/nouveau/Makefile
浏览文件 @
4f6029da
...
...
@@ -192,7 +192,7 @@ nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o
# drm/kms
nouveau-y
+=
nouveau_bios.o nouveau_fbcon.o nouveau_display.o
nouveau-y
+=
nouveau_connector.o nouveau_
hdmi.o nouveau_
dp.o
nouveau-y
+=
nouveau_connector.o nouveau_dp.o
nouveau-y
+=
nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o
# drm/kms/nv04:nv50
...
...
@@ -201,9 +201,7 @@ nouveau-y += nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o
nouveau-y
+=
nv04_crtc.o nv04_display.o nv04_cursor.o
# drm/kms/nv50-
nouveau-y
+=
nv50_display.o nvd0_display.o
nouveau-y
+=
nv50_crtc.o nv50_dac.o nv50_sor.o nv50_cursor.o
nouveau-y
+=
nv50_evo.o
nouveau-y
+=
nvd0_display.o
# drm/pm
nouveau-y
+=
nouveau_pm.o nouveau_volt.o nouveau_perf.o
...
...
drivers/gpu/drm/nouveau/nouveau_connector.h
浏览文件 @
4f6029da
...
...
@@ -28,6 +28,7 @@
#define __NOUVEAU_CONNECTOR_H__
#include <drm/drm_edid.h>
#include "nouveau_crtc.h"
struct
nouveau_i2c_port
;
...
...
@@ -80,6 +81,21 @@ static inline struct nouveau_connector *nouveau_connector(
return
container_of
(
con
,
struct
nouveau_connector
,
base
);
}
static
inline
struct
nouveau_connector
*
nouveau_crtc_connector_get
(
struct
nouveau_crtc
*
nv_crtc
)
{
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
drm_connector
*
connector
;
struct
drm_crtc
*
crtc
=
to_drm_crtc
(
nv_crtc
);
list_for_each_entry
(
connector
,
&
dev
->
mode_config
.
connector_list
,
head
)
{
if
(
connector
->
encoder
&&
connector
->
encoder
->
crtc
==
crtc
)
return
nouveau_connector
(
connector
);
}
return
NULL
;
}
struct
drm_connector
*
nouveau_connector_create
(
struct
drm_device
*
,
int
index
);
...
...
drivers/gpu/drm/nouveau/nouveau_crtc.h
浏览文件 @
4f6029da
...
...
@@ -91,7 +91,4 @@ int nv50_crtc_cursor_move(struct drm_crtc *drm_crtc, int x, int y);
int
nv04_cursor_init
(
struct
nouveau_crtc
*
);
int
nv50_cursor_init
(
struct
nouveau_crtc
*
);
struct
nouveau_connector
*
nouveau_crtc_connector_get
(
struct
nouveau_crtc
*
crtc
);
#endif
/* __NOUVEAU_CRTC_H__ */
drivers/gpu/drm/nouveau/nouveau_display.c
浏览文件 @
4f6029da
...
...
@@ -98,12 +98,12 @@ nouveau_framebuffer_init(struct drm_device *dev,
nv_fb
->
r_dma
=
NvEvoVRAM_LP
;
switch
(
fb
->
depth
)
{
case
8
:
nv_fb
->
r_format
=
NV50_EVO_CRTC_FB_DEPTH_8
;
break
;
case
15
:
nv_fb
->
r_format
=
NV50_EVO_CRTC_FB_DEPTH_15
;
break
;
case
16
:
nv_fb
->
r_format
=
NV50_EVO_CRTC_FB_DEPTH_16
;
break
;
case
8
:
nv_fb
->
r_format
=
0x1e00
;
break
;
case
15
:
nv_fb
->
r_format
=
0xe900
;
break
;
case
16
:
nv_fb
->
r_format
=
0xe800
;
break
;
case
24
:
case
32
:
nv_fb
->
r_format
=
NV50_EVO_CRTC_FB_DEPTH_24
;
break
;
case
30
:
nv_fb
->
r_format
=
NV50_EVO_CRTC_FB_DEPTH_3
0
;
break
;
case
32
:
nv_fb
->
r_format
=
0xcf00
;
break
;
case
30
:
nv_fb
->
r_format
=
0xd10
0
;
break
;
default:
NV_ERROR
(
drm
,
"unknown depth %d
\n
"
,
fb
->
depth
);
return
-
EINVAL
;
...
...
@@ -365,9 +365,6 @@ nouveau_display_create(struct drm_device *dev)
(
nouveau_modeset
<
0
&&
pclass
==
PCI_CLASS_DISPLAY_VGA
))
{
if
(
nv_device
(
drm
->
device
)
->
card_type
<
NV_50
)
ret
=
nv04_display_create
(
dev
);
else
if
(
nv_device
(
drm
->
device
)
->
card_type
<
NV_D0
)
ret
=
nv50_display_create
(
dev
);
else
ret
=
nvd0_display_create
(
dev
);
if
(
ret
)
...
...
@@ -660,10 +657,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/* Emit a page flip */
if
(
nv_device
(
drm
->
device
)
->
card_type
>=
NV_50
)
{
if
(
nv_device
(
drm
->
device
)
->
card_type
>=
NV_D0
)
ret
=
nvd0_display_flip_next
(
crtc
,
fb
,
chan
,
0
);
else
ret
=
nv50_display_flip_next
(
crtc
,
fb
,
chan
);
ret
=
nvd0_display_flip_next
(
crtc
,
fb
,
chan
,
0
);
if
(
ret
)
{
mutex_unlock
(
&
chan
->
cli
->
mutex
);
goto
fail_unreserve
;
...
...
drivers/gpu/drm/nouveau/nouveau_hdmi.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright 2011 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include <drm/drmP.h>
#include "nouveau_drm.h"
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include <core/class.h>
#include "nv50_display.h"
static
bool
hdmi_sor
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
if
(
nv_device
(
drm
->
device
)
->
chipset
<
0xa3
||
nv_device
(
drm
->
device
)
->
chipset
==
0xaa
||
nv_device
(
drm
->
device
)
->
chipset
==
0xac
)
return
false
;
return
true
;
}
static
void
nouveau_audio_disconnect
(
struct
drm_encoder
*
encoder
)
{
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
u32
or
=
nv_encoder
->
or
;
if
(
hdmi_sor
(
encoder
))
nv_exec
(
priv
->
core
,
NVA3_DISP_SOR_HDA_ELD
+
or
,
NULL
,
0
);
}
static
void
nouveau_audio_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
mode
)
{
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_connector
*
nv_connector
;
nv_connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
!
drm_detect_monitor_audio
(
nv_connector
->
edid
))
{
nouveau_audio_disconnect
(
encoder
);
return
;
}
if
(
hdmi_sor
(
encoder
))
{
drm_edid_to_eld
(
&
nv_connector
->
base
,
nv_connector
->
edid
);
nv_exec
(
priv
->
core
,
NVA3_DISP_SOR_HDA_ELD
+
nv_encoder
->
or
,
nv_connector
->
base
.
eld
,
nv_connector
->
base
.
eld
[
2
]
*
4
);
}
}
static
void
nouveau_hdmi_disconnect
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
nv_encoder
->
crtc
);
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
const
u32
moff
=
(
nv_crtc
->
index
<<
3
)
|
nv_encoder
->
or
;
nouveau_audio_disconnect
(
encoder
);
nv_call
(
priv
->
core
,
NV84_DISP_SOR_HDMI_PWR
+
moff
,
0x00000000
);
}
void
nouveau_hdmi_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
mode
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
nv_encoder
->
crtc
);
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
const
u32
moff
=
(
nv_crtc
->
index
<<
3
)
|
nv_encoder
->
or
;
struct
nouveau_connector
*
nv_connector
;
u32
max_ac_packet
,
rekey
;
nv_connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
!
mode
||
!
nv_connector
||
!
nv_connector
->
edid
||
!
drm_detect_hdmi_monitor
(
nv_connector
->
edid
))
{
nouveau_hdmi_disconnect
(
encoder
);
return
;
}
/* value matches nvidia binary driver, and tegra constant */
rekey
=
56
;
max_ac_packet
=
mode
->
htotal
-
mode
->
hdisplay
;
max_ac_packet
-=
rekey
;
max_ac_packet
-=
18
;
/* constant from tegra */
max_ac_packet
/=
32
;
nv_call
(
priv
->
core
,
NV84_DISP_SOR_HDMI_PWR
+
moff
,
NV84_DISP_SOR_HDMI_PWR_STATE_ON
|
(
max_ac_packet
<<
16
)
|
rekey
);
nouveau_audio_mode_set
(
encoder
,
mode
);
}
drivers/gpu/drm/nouveau/nv50_crtc.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "nouveau_reg.h"
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_gem.h"
#include "nouveau_hw.h"
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
#include "nouveau_connector.h"
#include "nv50_display.h"
#include <subdev/clock.h>
static
void
nv50_crtc_lut_load
(
struct
drm_crtc
*
crtc
)
{
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
void
__iomem
*
lut
=
nvbo_kmap_obj_iovirtual
(
nv_crtc
->
lut
.
nvbo
);
int
i
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
writew
(
nv_crtc
->
lut
.
r
[
i
]
>>
2
,
lut
+
8
*
i
+
0
);
writew
(
nv_crtc
->
lut
.
g
[
i
]
>>
2
,
lut
+
8
*
i
+
2
);
writew
(
nv_crtc
->
lut
.
b
[
i
]
>>
2
,
lut
+
8
*
i
+
4
);
}
if
(
nv_crtc
->
lut
.
depth
==
30
)
{
writew
(
nv_crtc
->
lut
.
r
[
i
-
1
]
>>
2
,
lut
+
8
*
i
+
0
);
writew
(
nv_crtc
->
lut
.
g
[
i
-
1
]
>>
2
,
lut
+
8
*
i
+
2
);
writew
(
nv_crtc
->
lut
.
b
[
i
-
1
]
>>
2
,
lut
+
8
*
i
+
4
);
}
}
int
nv50_crtc_blank
(
struct
nouveau_crtc
*
nv_crtc
,
bool
blanked
)
{
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
int
index
=
nv_crtc
->
index
,
ret
;
NV_DEBUG
(
drm
,
"index %d
\n
"
,
nv_crtc
->
index
);
NV_DEBUG
(
drm
,
"%s
\n
"
,
blanked
?
"blanked"
:
"unblanked"
);
if
(
blanked
)
{
nv_crtc
->
cursor
.
hide
(
nv_crtc
,
false
);
ret
=
RING_SPACE
(
evo
,
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
?
7
:
5
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while blanking crtc
\n
"
);
return
ret
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
index
,
CLUT_MODE
),
2
);
OUT_RING
(
evo
,
NV50_EVO_CRTC_CLUT_MODE_BLANK
);
OUT_RING
(
evo
,
0
);
if
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
)
{
BEGIN_NV04
(
evo
,
0
,
NV84_EVO_CRTC
(
index
,
CLUT_DMA
),
1
);
OUT_RING
(
evo
,
NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE
);
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
index
,
FB_DMA
),
1
);
OUT_RING
(
evo
,
NV50_EVO_CRTC_FB_DMA_HANDLE_NONE
);
}
else
{
if
(
nv_crtc
->
cursor
.
visible
)
nv_crtc
->
cursor
.
show
(
nv_crtc
,
false
);
else
nv_crtc
->
cursor
.
hide
(
nv_crtc
,
false
);
ret
=
RING_SPACE
(
evo
,
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
?
10
:
8
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while unblanking crtc
\n
"
);
return
ret
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
index
,
CLUT_MODE
),
2
);
OUT_RING
(
evo
,
nv_crtc
->
lut
.
depth
==
8
?
NV50_EVO_CRTC_CLUT_MODE_OFF
:
NV50_EVO_CRTC_CLUT_MODE_ON
);
OUT_RING
(
evo
,
nv_crtc
->
lut
.
nvbo
->
bo
.
offset
>>
8
);
if
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
)
{
BEGIN_NV04
(
evo
,
0
,
NV84_EVO_CRTC
(
index
,
CLUT_DMA
),
1
);
OUT_RING
(
evo
,
NvEvoVRAM
);
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
index
,
FB_OFFSET
),
2
);
OUT_RING
(
evo
,
nv_crtc
->
fb
.
offset
>>
8
);
OUT_RING
(
evo
,
0
);
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
index
,
FB_DMA
),
1
);
if
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
)
if
(
nv_crtc
->
fb
.
tile_flags
==
0x7a00
||
nv_crtc
->
fb
.
tile_flags
==
0xfe00
)
OUT_RING
(
evo
,
NvEvoFB32
);
else
if
(
nv_crtc
->
fb
.
tile_flags
==
0x7000
)
OUT_RING
(
evo
,
NvEvoFB16
);
else
OUT_RING
(
evo
,
NvEvoVRAM_LP
);
else
OUT_RING
(
evo
,
NvEvoVRAM_LP
);
}
nv_crtc
->
fb
.
blanked
=
blanked
;
return
0
;
}
static
int
nv50_crtc_set_dither
(
struct
nouveau_crtc
*
nv_crtc
,
bool
update
)
{
struct
nouveau_channel
*
evo
=
nv50_display
(
nv_crtc
->
base
.
dev
)
->
master
;
struct
nouveau_connector
*
nv_connector
;
struct
drm_connector
*
connector
;
int
head
=
nv_crtc
->
index
,
ret
;
u32
mode
=
0x00
;
nv_connector
=
nouveau_crtc_connector_get
(
nv_crtc
);
connector
=
&
nv_connector
->
base
;
if
(
nv_connector
->
dithering_mode
==
DITHERING_MODE_AUTO
)
{
if
(
nv_crtc
->
base
.
fb
->
depth
>
connector
->
display_info
.
bpc
*
3
)
mode
=
DITHERING_MODE_DYNAMIC2X2
;
}
else
{
mode
=
nv_connector
->
dithering_mode
;
}
if
(
nv_connector
->
dithering_depth
==
DITHERING_DEPTH_AUTO
)
{
if
(
connector
->
display_info
.
bpc
>=
8
)
mode
|=
DITHERING_DEPTH_8BPC
;
}
else
{
mode
|=
nv_connector
->
dithering_depth
;
}
ret
=
RING_SPACE
(
evo
,
2
+
(
update
?
2
:
0
));
if
(
ret
==
0
)
{
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
head
,
DITHER_CTRL
),
1
);
OUT_RING
(
evo
,
mode
);
if
(
update
)
{
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
FIRE_RING
(
evo
);
}
}
return
ret
;
}
static
int
nv50_crtc_set_color_vibrance
(
struct
nouveau_crtc
*
nv_crtc
,
bool
update
)
{
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
int
ret
;
int
adj
;
u32
hue
,
vib
;
NV_DEBUG
(
drm
,
"vibrance = %i, hue = %i
\n
"
,
nv_crtc
->
color_vibrance
,
nv_crtc
->
vibrant_hue
);
ret
=
RING_SPACE
(
evo
,
2
+
(
update
?
2
:
0
));
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while setting color vibrance
\n
"
);
return
ret
;
}
adj
=
(
nv_crtc
->
color_vibrance
>
0
)
?
50
:
0
;
vib
=
((
nv_crtc
->
color_vibrance
*
2047
+
adj
)
/
100
)
&
0xfff
;
hue
=
((
nv_crtc
->
vibrant_hue
*
2047
)
/
100
)
&
0xfff
;
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
COLOR_CTRL
),
1
);
OUT_RING
(
evo
,
(
hue
<<
20
)
|
(
vib
<<
8
));
if
(
update
)
{
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
FIRE_RING
(
evo
);
}
return
0
;
}
struct
nouveau_connector
*
nouveau_crtc_connector_get
(
struct
nouveau_crtc
*
nv_crtc
)
{
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
drm_connector
*
connector
;
struct
drm_crtc
*
crtc
=
to_drm_crtc
(
nv_crtc
);
/* The safest approach is to find an encoder with the right crtc, that
* is also linked to a connector. */
list_for_each_entry
(
connector
,
&
dev
->
mode_config
.
connector_list
,
head
)
{
if
(
connector
->
encoder
)
if
(
connector
->
encoder
->
crtc
==
crtc
)
return
nouveau_connector
(
connector
);
}
return
NULL
;
}
static
int
nv50_crtc_set_scale
(
struct
nouveau_crtc
*
nv_crtc
,
bool
update
)
{
struct
nouveau_connector
*
nv_connector
;
struct
drm_crtc
*
crtc
=
&
nv_crtc
->
base
;
struct
drm_device
*
dev
=
crtc
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
struct
drm_display_mode
*
umode
=
&
crtc
->
mode
;
struct
drm_display_mode
*
omode
;
int
scaling_mode
,
ret
;
u32
ctrl
=
0
,
oX
,
oY
;
nv_connector
=
nouveau_crtc_connector_get
(
nv_crtc
);
if
(
!
nv_connector
||
!
nv_connector
->
native_mode
)
{
NV_ERROR
(
drm
,
"no native mode, forcing panel scaling
\n
"
);
scaling_mode
=
DRM_MODE_SCALE_NONE
;
}
else
{
scaling_mode
=
nv_connector
->
scaling_mode
;
}
/* start off at the resolution we programmed the crtc for, this
* effectively handles NONE/FULL scaling
*/
if
(
scaling_mode
!=
DRM_MODE_SCALE_NONE
)
omode
=
nv_connector
->
native_mode
;
else
omode
=
umode
;
oX
=
omode
->
hdisplay
;
oY
=
omode
->
vdisplay
;
if
(
omode
->
flags
&
DRM_MODE_FLAG_DBLSCAN
)
oY
*=
2
;
/* add overscan compensation if necessary, will keep the aspect
* ratio the same as the backend mode unless overridden by the
* user setting both hborder and vborder properties.
*/
if
(
nv_connector
&&
(
nv_connector
->
underscan
==
UNDERSCAN_ON
||
(
nv_connector
->
underscan
==
UNDERSCAN_AUTO
&&
nv_connector
->
edid
&&
drm_detect_hdmi_monitor
(
nv_connector
->
edid
))))
{
u32
bX
=
nv_connector
->
underscan_hborder
;
u32
bY
=
nv_connector
->
underscan_vborder
;
u32
aspect
=
(
oY
<<
19
)
/
oX
;
if
(
bX
)
{
oX
-=
(
bX
*
2
);
if
(
bY
)
oY
-=
(
bY
*
2
);
else
oY
=
((
oX
*
aspect
)
+
(
aspect
/
2
))
>>
19
;
}
else
{
oX
-=
(
oX
>>
4
)
+
32
;
if
(
bY
)
oY
-=
(
bY
*
2
);
else
oY
=
((
oX
*
aspect
)
+
(
aspect
/
2
))
>>
19
;
}
}
/* handle CENTER/ASPECT scaling, taking into account the areas
* removed already for overscan compensation
*/
switch
(
scaling_mode
)
{
case
DRM_MODE_SCALE_CENTER
:
oX
=
min
((
u32
)
umode
->
hdisplay
,
oX
);
oY
=
min
((
u32
)
umode
->
vdisplay
,
oY
);
/* fall-through */
case
DRM_MODE_SCALE_ASPECT
:
if
(
oY
<
oX
)
{
u32
aspect
=
(
umode
->
hdisplay
<<
19
)
/
umode
->
vdisplay
;
oX
=
((
oY
*
aspect
)
+
(
aspect
/
2
))
>>
19
;
}
else
{
u32
aspect
=
(
umode
->
vdisplay
<<
19
)
/
umode
->
hdisplay
;
oY
=
((
oX
*
aspect
)
+
(
aspect
/
2
))
>>
19
;
}
break
;
default:
break
;
}
if
(
umode
->
hdisplay
!=
oX
||
umode
->
vdisplay
!=
oY
||
umode
->
flags
&
DRM_MODE_FLAG_INTERLACE
||
umode
->
flags
&
DRM_MODE_FLAG_DBLSCAN
)
ctrl
|=
NV50_EVO_CRTC_SCALE_CTRL_ACTIVE
;
ret
=
RING_SPACE
(
evo
,
5
);
if
(
ret
)
return
ret
;
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
SCALE_CTRL
),
1
);
OUT_RING
(
evo
,
ctrl
);
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
SCALE_RES1
),
2
);
OUT_RING
(
evo
,
oY
<<
16
|
oX
);
OUT_RING
(
evo
,
oY
<<
16
|
oX
);
if
(
update
)
{
nv50_display_flip_stop
(
crtc
);
nv50_display_sync
(
dev
);
nv50_display_flip_next
(
crtc
,
crtc
->
fb
,
NULL
);
}
return
0
;
}
int
nv50_crtc_set_clock
(
struct
drm_device
*
dev
,
int
head
,
int
pclk
)
{
struct
nouveau_device
*
device
=
nouveau_dev
(
dev
);
struct
nouveau_clock
*
clk
=
nouveau_clock
(
device
);
return
clk
->
pll_set
(
clk
,
PLL_VPLL0
+
head
,
pclk
);
}
static
void
nv50_crtc_destroy
(
struct
drm_crtc
*
crtc
)
{
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
nouveau_bo_unmap
(
nv_crtc
->
lut
.
nvbo
);
nouveau_bo_ref
(
NULL
,
&
nv_crtc
->
lut
.
nvbo
);
nouveau_bo_unmap
(
nv_crtc
->
cursor
.
nvbo
);
nouveau_bo_ref
(
NULL
,
&
nv_crtc
->
cursor
.
nvbo
);
drm_crtc_cleanup
(
&
nv_crtc
->
base
);
kfree
(
nv_crtc
);
}
int
nv50_crtc_cursor_set
(
struct
drm_crtc
*
crtc
,
struct
drm_file
*
file_priv
,
uint32_t
buffer_handle
,
uint32_t
width
,
uint32_t
height
)
{
struct
drm_device
*
dev
=
crtc
->
dev
;
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
struct
nouveau_bo
*
cursor
=
NULL
;
struct
drm_gem_object
*
gem
;
int
ret
=
0
,
i
;
if
(
!
buffer_handle
)
{
nv_crtc
->
cursor
.
hide
(
nv_crtc
,
true
);
return
0
;
}
if
(
width
!=
64
||
height
!=
64
)
return
-
EINVAL
;
gem
=
drm_gem_object_lookup
(
dev
,
file_priv
,
buffer_handle
);
if
(
!
gem
)
return
-
ENOENT
;
cursor
=
nouveau_gem_object
(
gem
);
ret
=
nouveau_bo_map
(
cursor
);
if
(
ret
)
goto
out
;
/* The simple will do for now. */
for
(
i
=
0
;
i
<
64
*
64
;
i
++
)
nouveau_bo_wr32
(
nv_crtc
->
cursor
.
nvbo
,
i
,
nouveau_bo_rd32
(
cursor
,
i
));
nouveau_bo_unmap
(
cursor
);
nv_crtc
->
cursor
.
set_offset
(
nv_crtc
,
nv_crtc
->
cursor
.
nvbo
->
bo
.
offset
);
nv_crtc
->
cursor
.
show
(
nv_crtc
,
true
);
out:
drm_gem_object_unreference_unlocked
(
gem
);
return
ret
;
}
int
nv50_crtc_cursor_move
(
struct
drm_crtc
*
crtc
,
int
x
,
int
y
)
{
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
nv_crtc
->
cursor
.
set_pos
(
nv_crtc
,
x
,
y
);
return
0
;
}
static
void
nv50_crtc_gamma_set
(
struct
drm_crtc
*
crtc
,
u16
*
r
,
u16
*
g
,
u16
*
b
,
uint32_t
start
,
uint32_t
size
)
{
int
end
=
(
start
+
size
>
256
)
?
256
:
start
+
size
,
i
;
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
for
(
i
=
start
;
i
<
end
;
i
++
)
{
nv_crtc
->
lut
.
r
[
i
]
=
r
[
i
];
nv_crtc
->
lut
.
g
[
i
]
=
g
[
i
];
nv_crtc
->
lut
.
b
[
i
]
=
b
[
i
];
}
/* We need to know the depth before we upload, but it's possible to
* get called before a framebuffer is bound. If this is the case,
* mark the lut values as dirty by setting depth==0, and it'll be
* uploaded on the first mode_set_base()
*/
if
(
!
nv_crtc
->
base
.
fb
)
{
nv_crtc
->
lut
.
depth
=
0
;
return
;
}
nv50_crtc_lut_load
(
crtc
);
}
static
void
nv50_crtc_save
(
struct
drm_crtc
*
crtc
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
crtc
->
dev
);
NV_ERROR
(
drm
,
"!!
\n
"
);
}
static
void
nv50_crtc_restore
(
struct
drm_crtc
*
crtc
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
crtc
->
dev
);
NV_ERROR
(
drm
,
"!!
\n
"
);
}
static
const
struct
drm_crtc_funcs
nv50_crtc_funcs
=
{
.
save
=
nv50_crtc_save
,
.
restore
=
nv50_crtc_restore
,
.
cursor_set
=
nv50_crtc_cursor_set
,
.
cursor_move
=
nv50_crtc_cursor_move
,
.
gamma_set
=
nv50_crtc_gamma_set
,
.
set_config
=
drm_crtc_helper_set_config
,
.
page_flip
=
nouveau_crtc_page_flip
,
.
destroy
=
nv50_crtc_destroy
,
};
static
void
nv50_crtc_dpms
(
struct
drm_crtc
*
crtc
,
int
mode
)
{
}
static
void
nv50_crtc_prepare
(
struct
drm_crtc
*
crtc
)
{
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
struct
drm_device
*
dev
=
crtc
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
NV_DEBUG
(
drm
,
"index %d
\n
"
,
nv_crtc
->
index
);
nv50_display_flip_stop
(
crtc
);
drm_vblank_pre_modeset
(
dev
,
nv_crtc
->
index
);
nv50_crtc_blank
(
nv_crtc
,
true
);
}
static
void
nv50_crtc_commit
(
struct
drm_crtc
*
crtc
)
{
struct
drm_device
*
dev
=
crtc
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
NV_DEBUG
(
drm
,
"index %d
\n
"
,
nv_crtc
->
index
);
nv50_crtc_blank
(
nv_crtc
,
false
);
drm_vblank_post_modeset
(
dev
,
nv_crtc
->
index
);
nv50_display_sync
(
dev
);
nv50_display_flip_next
(
crtc
,
crtc
->
fb
,
NULL
);
}
static
bool
nv50_crtc_mode_fixup
(
struct
drm_crtc
*
crtc
,
const
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
{
return
true
;
}
static
int
nv50_crtc_do_mode_set_base
(
struct
drm_crtc
*
crtc
,
struct
drm_framebuffer
*
passed_fb
,
int
x
,
int
y
,
bool
atomic
)
{
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
struct
drm_framebuffer
*
drm_fb
;
struct
nouveau_framebuffer
*
fb
;
int
ret
;
NV_DEBUG
(
drm
,
"index %d
\n
"
,
nv_crtc
->
index
);
/* no fb bound */
if
(
!
atomic
&&
!
crtc
->
fb
)
{
NV_DEBUG
(
drm
,
"No FB bound
\n
"
);
return
0
;
}
/* If atomic, we want to switch to the fb we were passed, so
* now we update pointers to do that. (We don't pin; just
* assume we're already pinned and update the base address.)
*/
if
(
atomic
)
{
drm_fb
=
passed_fb
;
fb
=
nouveau_framebuffer
(
passed_fb
);
}
else
{
drm_fb
=
crtc
->
fb
;
fb
=
nouveau_framebuffer
(
crtc
->
fb
);
/* If not atomic, we can go ahead and pin, and unpin the
* old fb we were passed.
*/
ret
=
nouveau_bo_pin
(
fb
->
nvbo
,
TTM_PL_FLAG_VRAM
);
if
(
ret
)
return
ret
;
if
(
passed_fb
)
{
struct
nouveau_framebuffer
*
ofb
=
nouveau_framebuffer
(
passed_fb
);
nouveau_bo_unpin
(
ofb
->
nvbo
);
}
}
nv_crtc
->
fb
.
offset
=
fb
->
nvbo
->
bo
.
offset
;
nv_crtc
->
fb
.
tile_flags
=
nouveau_bo_tile_layout
(
fb
->
nvbo
);
nv_crtc
->
fb
.
cpp
=
drm_fb
->
bits_per_pixel
/
8
;
if
(
!
nv_crtc
->
fb
.
blanked
&&
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
)
{
ret
=
RING_SPACE
(
evo
,
2
);
if
(
ret
)
return
ret
;
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
FB_DMA
),
1
);
OUT_RING
(
evo
,
fb
->
r_dma
);
}
ret
=
RING_SPACE
(
evo
,
12
);
if
(
ret
)
return
ret
;
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
FB_OFFSET
),
5
);
OUT_RING
(
evo
,
nv_crtc
->
fb
.
offset
>>
8
);
OUT_RING
(
evo
,
0
);
OUT_RING
(
evo
,
(
drm_fb
->
height
<<
16
)
|
drm_fb
->
width
);
OUT_RING
(
evo
,
fb
->
r_pitch
);
OUT_RING
(
evo
,
fb
->
r_format
);
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
CLUT_MODE
),
1
);
OUT_RING
(
evo
,
fb
->
base
.
depth
==
8
?
NV50_EVO_CRTC_CLUT_MODE_OFF
:
NV50_EVO_CRTC_CLUT_MODE_ON
);
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
FB_POS
),
1
);
OUT_RING
(
evo
,
(
y
<<
16
)
|
x
);
if
(
nv_crtc
->
lut
.
depth
!=
fb
->
base
.
depth
)
{
nv_crtc
->
lut
.
depth
=
fb
->
base
.
depth
;
nv50_crtc_lut_load
(
crtc
);
}
return
0
;
}
static
int
nv50_crtc_mode_set
(
struct
drm_crtc
*
crtc
,
struct
drm_display_mode
*
umode
,
struct
drm_display_mode
*
mode
,
int
x
,
int
y
,
struct
drm_framebuffer
*
old_fb
)
{
struct
drm_device
*
dev
=
crtc
->
dev
;
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
u32
head
=
nv_crtc
->
index
*
0x400
;
u32
ilace
=
(
mode
->
flags
&
DRM_MODE_FLAG_INTERLACE
)
?
2
:
1
;
u32
vscan
=
(
mode
->
flags
&
DRM_MODE_FLAG_DBLSCAN
)
?
2
:
1
;
u32
hactive
,
hsynce
,
hbackp
,
hfrontp
,
hblanke
,
hblanks
;
u32
vactive
,
vsynce
,
vbackp
,
vfrontp
,
vblanke
,
vblanks
;
u32
vblan2e
=
0
,
vblan2s
=
1
;
int
ret
;
/* hw timing description looks like this:
*
* <sync> <back porch> <---------display---------> <front porch>
* ______
* |____________|---------------------------|____________|
*
* ^ synce ^ blanke ^ blanks ^ active
*
* interlaced modes also have 2 additional values pointing at the end
* and start of the next field's blanking period.
*/
hactive
=
mode
->
htotal
;
hsynce
=
mode
->
hsync_end
-
mode
->
hsync_start
-
1
;
hbackp
=
mode
->
htotal
-
mode
->
hsync_end
;
hblanke
=
hsynce
+
hbackp
;
hfrontp
=
mode
->
hsync_start
-
mode
->
hdisplay
;
hblanks
=
mode
->
htotal
-
hfrontp
-
1
;
vactive
=
mode
->
vtotal
*
vscan
/
ilace
;
vsynce
=
((
mode
->
vsync_end
-
mode
->
vsync_start
)
*
vscan
/
ilace
)
-
1
;
vbackp
=
(
mode
->
vtotal
-
mode
->
vsync_end
)
*
vscan
/
ilace
;
vblanke
=
vsynce
+
vbackp
;
vfrontp
=
(
mode
->
vsync_start
-
mode
->
vdisplay
)
*
vscan
/
ilace
;
vblanks
=
vactive
-
vfrontp
-
1
;
if
(
mode
->
flags
&
DRM_MODE_FLAG_INTERLACE
)
{
vblan2e
=
vactive
+
vsynce
+
vbackp
;
vblan2s
=
vblan2e
+
(
mode
->
vdisplay
*
vscan
/
ilace
);
vactive
=
(
vactive
*
2
)
+
1
;
}
ret
=
RING_SPACE
(
evo
,
18
);
if
(
ret
==
0
)
{
BEGIN_NV04
(
evo
,
0
,
0x0804
+
head
,
2
);
OUT_RING
(
evo
,
0x00800000
|
mode
->
clock
);
OUT_RING
(
evo
,
(
ilace
==
2
)
?
2
:
0
);
BEGIN_NV04
(
evo
,
0
,
0x0810
+
head
,
6
);
OUT_RING
(
evo
,
0x00000000
);
/* border colour */
OUT_RING
(
evo
,
(
vactive
<<
16
)
|
hactive
);
OUT_RING
(
evo
,
(
vsynce
<<
16
)
|
hsynce
);
OUT_RING
(
evo
,
(
vblanke
<<
16
)
|
hblanke
);
OUT_RING
(
evo
,
(
vblanks
<<
16
)
|
hblanks
);
OUT_RING
(
evo
,
(
vblan2e
<<
16
)
|
vblan2s
);
BEGIN_NV04
(
evo
,
0
,
0x082c
+
head
,
1
);
OUT_RING
(
evo
,
0x00000000
);
BEGIN_NV04
(
evo
,
0
,
0x0900
+
head
,
1
);
OUT_RING
(
evo
,
0x00000311
);
/* makes sync channel work */
BEGIN_NV04
(
evo
,
0
,
0x08c8
+
head
,
1
);
OUT_RING
(
evo
,
(
umode
->
vdisplay
<<
16
)
|
umode
->
hdisplay
);
BEGIN_NV04
(
evo
,
0
,
0x08d4
+
head
,
1
);
OUT_RING
(
evo
,
0x00000000
);
/* screen position */
}
nv_crtc
->
set_dither
(
nv_crtc
,
false
);
nv_crtc
->
set_scale
(
nv_crtc
,
false
);
nv_crtc
->
set_color_vibrance
(
nv_crtc
,
false
);
return
nv50_crtc_do_mode_set_base
(
crtc
,
old_fb
,
x
,
y
,
false
);
}
static
int
nv50_crtc_mode_set_base
(
struct
drm_crtc
*
crtc
,
int
x
,
int
y
,
struct
drm_framebuffer
*
old_fb
)
{
int
ret
;
nv50_display_flip_stop
(
crtc
);
ret
=
nv50_crtc_do_mode_set_base
(
crtc
,
old_fb
,
x
,
y
,
false
);
if
(
ret
)
return
ret
;
ret
=
nv50_display_sync
(
crtc
->
dev
);
if
(
ret
)
return
ret
;
return
nv50_display_flip_next
(
crtc
,
crtc
->
fb
,
NULL
);
}
static
int
nv50_crtc_mode_set_base_atomic
(
struct
drm_crtc
*
crtc
,
struct
drm_framebuffer
*
fb
,
int
x
,
int
y
,
enum
mode_set_atomic
state
)
{
int
ret
;
nv50_display_flip_stop
(
crtc
);
ret
=
nv50_crtc_do_mode_set_base
(
crtc
,
fb
,
x
,
y
,
true
);
if
(
ret
)
return
ret
;
return
nv50_display_sync
(
crtc
->
dev
);
}
static
const
struct
drm_crtc_helper_funcs
nv50_crtc_helper_funcs
=
{
.
dpms
=
nv50_crtc_dpms
,
.
prepare
=
nv50_crtc_prepare
,
.
commit
=
nv50_crtc_commit
,
.
mode_fixup
=
nv50_crtc_mode_fixup
,
.
mode_set
=
nv50_crtc_mode_set
,
.
mode_set_base
=
nv50_crtc_mode_set_base
,
.
mode_set_base_atomic
=
nv50_crtc_mode_set_base_atomic
,
.
load_lut
=
nv50_crtc_lut_load
,
};
int
nv50_crtc_create
(
struct
drm_device
*
dev
,
int
index
)
{
struct
nouveau_crtc
*
nv_crtc
=
NULL
;
int
ret
,
i
;
nv_crtc
=
kzalloc
(
sizeof
(
*
nv_crtc
),
GFP_KERNEL
);
if
(
!
nv_crtc
)
return
-
ENOMEM
;
nv_crtc
->
index
=
index
;
nv_crtc
->
set_dither
=
nv50_crtc_set_dither
;
nv_crtc
->
set_scale
=
nv50_crtc_set_scale
;
nv_crtc
->
set_color_vibrance
=
nv50_crtc_set_color_vibrance
;
nv_crtc
->
color_vibrance
=
50
;
nv_crtc
->
vibrant_hue
=
0
;
nv_crtc
->
lut
.
depth
=
0
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
nv_crtc
->
lut
.
r
[
i
]
=
i
<<
8
;
nv_crtc
->
lut
.
g
[
i
]
=
i
<<
8
;
nv_crtc
->
lut
.
b
[
i
]
=
i
<<
8
;
}
drm_crtc_init
(
dev
,
&
nv_crtc
->
base
,
&
nv50_crtc_funcs
);
drm_crtc_helper_add
(
&
nv_crtc
->
base
,
&
nv50_crtc_helper_funcs
);
drm_mode_crtc_set_gamma_size
(
&
nv_crtc
->
base
,
256
);
ret
=
nouveau_bo_new
(
dev
,
4096
,
0x100
,
TTM_PL_FLAG_VRAM
,
0
,
0x0000
,
NULL
,
&
nv_crtc
->
lut
.
nvbo
);
if
(
!
ret
)
{
ret
=
nouveau_bo_pin
(
nv_crtc
->
lut
.
nvbo
,
TTM_PL_FLAG_VRAM
);
if
(
!
ret
)
ret
=
nouveau_bo_map
(
nv_crtc
->
lut
.
nvbo
);
if
(
ret
)
nouveau_bo_ref
(
NULL
,
&
nv_crtc
->
lut
.
nvbo
);
}
if
(
ret
)
goto
out
;
ret
=
nouveau_bo_new
(
dev
,
64
*
64
*
4
,
0x100
,
TTM_PL_FLAG_VRAM
,
0
,
0x0000
,
NULL
,
&
nv_crtc
->
cursor
.
nvbo
);
if
(
!
ret
)
{
ret
=
nouveau_bo_pin
(
nv_crtc
->
cursor
.
nvbo
,
TTM_PL_FLAG_VRAM
);
if
(
!
ret
)
ret
=
nouveau_bo_map
(
nv_crtc
->
cursor
.
nvbo
);
if
(
ret
)
nouveau_bo_ref
(
NULL
,
&
nv_crtc
->
cursor
.
nvbo
);
}
if
(
ret
)
goto
out
;
nv50_cursor_init
(
nv_crtc
);
out:
if
(
ret
)
nv50_crtc_destroy
(
&
nv_crtc
->
base
);
return
ret
;
}
drivers/gpu/drm/nouveau/nv50_cursor.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <drm/drmP.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_crtc.h"
#include "nv50_display.h"
static
void
nv50_cursor_show
(
struct
nouveau_crtc
*
nv_crtc
,
bool
update
)
{
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
int
ret
;
if
(
update
&&
nv_crtc
->
cursor
.
visible
)
return
;
ret
=
RING_SPACE
(
evo
,
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
?
5
:
3
)
+
update
*
2
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while unhiding cursor
\n
"
);
return
;
}
if
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
)
{
BEGIN_NV04
(
evo
,
0
,
NV84_EVO_CRTC
(
nv_crtc
->
index
,
CURSOR_DMA
),
1
);
OUT_RING
(
evo
,
NvEvoVRAM
);
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
CURSOR_CTRL
),
2
);
OUT_RING
(
evo
,
NV50_EVO_CRTC_CURSOR_CTRL_SHOW
);
OUT_RING
(
evo
,
nv_crtc
->
cursor
.
offset
>>
8
);
if
(
update
)
{
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
FIRE_RING
(
evo
);
nv_crtc
->
cursor
.
visible
=
true
;
}
}
static
void
nv50_cursor_hide
(
struct
nouveau_crtc
*
nv_crtc
,
bool
update
)
{
struct
drm_device
*
dev
=
nv_crtc
->
base
.
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
int
ret
;
if
(
update
&&
!
nv_crtc
->
cursor
.
visible
)
return
;
ret
=
RING_SPACE
(
evo
,
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
?
5
:
3
)
+
update
*
2
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while hiding cursor
\n
"
);
return
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_CRTC
(
nv_crtc
->
index
,
CURSOR_CTRL
),
2
);
OUT_RING
(
evo
,
NV50_EVO_CRTC_CURSOR_CTRL_HIDE
);
OUT_RING
(
evo
,
0
);
if
(
nv_device
(
drm
->
device
)
->
chipset
!=
0x50
)
{
BEGIN_NV04
(
evo
,
0
,
NV84_EVO_CRTC
(
nv_crtc
->
index
,
CURSOR_DMA
),
1
);
OUT_RING
(
evo
,
NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE
);
}
if
(
update
)
{
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
FIRE_RING
(
evo
);
nv_crtc
->
cursor
.
visible
=
false
;
}
}
static
void
nv50_cursor_set_pos
(
struct
nouveau_crtc
*
nv_crtc
,
int
x
,
int
y
)
{
struct
nouveau_device
*
device
=
nouveau_dev
(
nv_crtc
->
base
.
dev
);
nv_crtc
->
cursor_saved_x
=
x
;
nv_crtc
->
cursor_saved_y
=
y
;
nv_wr32
(
device
,
NV50_PDISPLAY_CURSOR_USER_POS
(
nv_crtc
->
index
),
((
y
&
0xFFFF
)
<<
16
)
|
(
x
&
0xFFFF
));
/* Needed to make the cursor move. */
nv_wr32
(
device
,
NV50_PDISPLAY_CURSOR_USER_POS_CTRL
(
nv_crtc
->
index
),
0
);
}
static
void
nv50_cursor_set_offset
(
struct
nouveau_crtc
*
nv_crtc
,
uint32_t
offset
)
{
if
(
offset
==
nv_crtc
->
cursor
.
offset
)
return
;
nv_crtc
->
cursor
.
offset
=
offset
;
if
(
nv_crtc
->
cursor
.
visible
)
{
nv_crtc
->
cursor
.
visible
=
false
;
nv_crtc
->
cursor
.
show
(
nv_crtc
,
true
);
}
}
int
nv50_cursor_init
(
struct
nouveau_crtc
*
nv_crtc
)
{
nv_crtc
->
cursor
.
set_offset
=
nv50_cursor_set_offset
;
nv_crtc
->
cursor
.
set_pos
=
nv50_cursor_set_pos
;
nv_crtc
->
cursor
.
hide
=
nv50_cursor_hide
;
nv_crtc
->
cursor
.
show
=
nv50_cursor_show
;
return
0
;
}
drivers/gpu/drm/nouveau/nv50_dac.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
#include "nouveau_reg.h"
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_encoder.h"
#include "nouveau_connector.h"
#include "nouveau_crtc.h"
#include "nv50_display.h"
#include <core/class.h>
#include <subdev/timer.h>
static
void
nv50_dac_disconnect
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
int
ret
;
if
(
!
nv_encoder
->
crtc
)
return
;
nv50_crtc_blank
(
nouveau_crtc
(
nv_encoder
->
crtc
),
true
);
NV_DEBUG
(
drm
,
"Disconnecting DAC %d
\n
"
,
nv_encoder
->
or
);
ret
=
RING_SPACE
(
evo
,
4
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while disconnecting DAC
\n
"
);
return
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_DAC
(
nv_encoder
->
or
,
MODE_CTRL
),
1
);
OUT_RING
(
evo
,
0
);
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
nv_encoder
->
crtc
=
NULL
;
}
static
enum
drm_connector_status
nv50_dac_detect
(
struct
drm_encoder
*
encoder
,
struct
drm_connector
*
connector
)
{
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
int
or
=
nv_encoder
->
or
,
ret
;
u32
load
;
if
(
drm
->
vbios
.
dactestval
)
load
=
drm
->
vbios
.
dactestval
;
else
load
=
340
;
ret
=
nv_exec
(
priv
->
core
,
NV50_DISP_DAC_LOAD
+
or
,
&
load
,
sizeof
(
load
));
if
(
ret
||
load
!=
7
)
return
connector_status_disconnected
;
return
connector_status_connected
;
}
static
void
nv50_dac_dpms
(
struct
drm_encoder
*
encoder
,
int
mode
)
{
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
uint32_t
val
;
int
or
=
nv_encoder
->
or
;
NV_DEBUG
(
drm
,
"or %d mode %d
\n
"
,
or
,
mode
);
if
(
mode
!=
DRM_MODE_DPMS_ON
)
val
=
NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED
;
else
val
=
0
;
switch
(
mode
)
{
case
DRM_MODE_DPMS_STANDBY
:
val
|=
NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF
;
break
;
case
DRM_MODE_DPMS_SUSPEND
:
val
|=
NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF
;
break
;
case
DRM_MODE_DPMS_OFF
:
val
|=
NV50_PDISPLAY_DAC_DPMS_CTRL_OFF
;
val
|=
NV50_PDISPLAY_DAC_DPMS_CTRL_HSYNC_OFF
;
val
|=
NV50_PDISPLAY_DAC_DPMS_CTRL_VSYNC_OFF
;
break
;
default:
break
;
}
nv_call
(
priv
->
core
,
NV50_DISP_DAC_PWR
+
or
,
val
);
}
static
void
nv50_dac_save
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
NV_ERROR
(
drm
,
"!!
\n
"
);
}
static
void
nv50_dac_restore
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
NV_ERROR
(
drm
,
"!!
\n
"
);
}
static
bool
nv50_dac_mode_fixup
(
struct
drm_encoder
*
encoder
,
const
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_connector
*
connector
;
NV_DEBUG
(
drm
,
"or %d
\n
"
,
nv_encoder
->
or
);
connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
!
connector
)
{
NV_ERROR
(
drm
,
"Encoder has no connector
\n
"
);
return
false
;
}
if
(
connector
->
scaling_mode
!=
DRM_MODE_SCALE_NONE
&&
connector
->
native_mode
)
drm_mode_copy
(
adjusted_mode
,
connector
->
native_mode
);
return
true
;
}
static
void
nv50_dac_commit
(
struct
drm_encoder
*
encoder
)
{
}
static
void
nv50_dac_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
struct
nouveau_crtc
*
crtc
=
nouveau_crtc
(
encoder
->
crtc
);
uint32_t
mode_ctl
=
0
,
mode_ctl2
=
0
;
int
ret
;
NV_DEBUG
(
drm
,
"or %d type %d crtc %d
\n
"
,
nv_encoder
->
or
,
nv_encoder
->
dcb
->
type
,
crtc
->
index
);
nv50_dac_dpms
(
encoder
,
DRM_MODE_DPMS_ON
);
if
(
crtc
->
index
==
1
)
mode_ctl
|=
NV50_EVO_DAC_MODE_CTRL_CRTC1
;
else
mode_ctl
|=
NV50_EVO_DAC_MODE_CTRL_CRTC0
;
/* Lacking a working tv-out, this is not a 100% sure. */
if
(
nv_encoder
->
dcb
->
type
==
DCB_OUTPUT_ANALOG
)
mode_ctl
|=
0x40
;
else
if
(
nv_encoder
->
dcb
->
type
==
DCB_OUTPUT_TV
)
mode_ctl
|=
0x100
;
if
(
adjusted_mode
->
flags
&
DRM_MODE_FLAG_NHSYNC
)
mode_ctl2
|=
NV50_EVO_DAC_MODE_CTRL2_NHSYNC
;
if
(
adjusted_mode
->
flags
&
DRM_MODE_FLAG_NVSYNC
)
mode_ctl2
|=
NV50_EVO_DAC_MODE_CTRL2_NVSYNC
;
ret
=
RING_SPACE
(
evo
,
3
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while connecting DAC
\n
"
);
return
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_DAC
(
nv_encoder
->
or
,
MODE_CTRL
),
2
);
OUT_RING
(
evo
,
mode_ctl
);
OUT_RING
(
evo
,
mode_ctl2
);
nv_encoder
->
crtc
=
encoder
->
crtc
;
}
static
struct
drm_crtc
*
nv50_dac_crtc_get
(
struct
drm_encoder
*
encoder
)
{
return
nouveau_encoder
(
encoder
)
->
crtc
;
}
static
const
struct
drm_encoder_helper_funcs
nv50_dac_helper_funcs
=
{
.
dpms
=
nv50_dac_dpms
,
.
save
=
nv50_dac_save
,
.
restore
=
nv50_dac_restore
,
.
mode_fixup
=
nv50_dac_mode_fixup
,
.
prepare
=
nv50_dac_disconnect
,
.
commit
=
nv50_dac_commit
,
.
mode_set
=
nv50_dac_mode_set
,
.
get_crtc
=
nv50_dac_crtc_get
,
.
detect
=
nv50_dac_detect
,
.
disable
=
nv50_dac_disconnect
};
static
void
nv50_dac_destroy
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
if
(
!
encoder
)
return
;
drm_encoder_cleanup
(
encoder
);
kfree
(
nv_encoder
);
}
static
const
struct
drm_encoder_funcs
nv50_dac_encoder_funcs
=
{
.
destroy
=
nv50_dac_destroy
,
};
int
nv50_dac_create
(
struct
drm_connector
*
connector
,
struct
dcb_output
*
entry
)
{
struct
nouveau_encoder
*
nv_encoder
;
struct
drm_encoder
*
encoder
;
nv_encoder
=
kzalloc
(
sizeof
(
*
nv_encoder
),
GFP_KERNEL
);
if
(
!
nv_encoder
)
return
-
ENOMEM
;
encoder
=
to_drm_encoder
(
nv_encoder
);
nv_encoder
->
dcb
=
entry
;
nv_encoder
->
or
=
ffs
(
entry
->
or
)
-
1
;
drm_encoder_init
(
connector
->
dev
,
encoder
,
&
nv50_dac_encoder_funcs
,
DRM_MODE_ENCODER_DAC
);
drm_encoder_helper_add
(
encoder
,
&
nv50_dac_helper_funcs
);
encoder
->
possible_crtcs
=
entry
->
heads
;
encoder
->
possible_clones
=
0
;
drm_mode_connector_attach_encoder
(
connector
,
encoder
);
return
0
;
}
drivers/gpu/drm/nouveau/nv50_display.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nv50_display.h"
#include "nouveau_crtc.h"
#include "nouveau_encoder.h"
#include "nouveau_connector.h"
#include "nouveau_fbcon.h"
#include <drm/drm_crtc_helper.h>
#include "nouveau_fence.h"
#include <core/gpuobj.h>
#include <core/class.h>
#include <subdev/timer.h>
static
inline
int
nv50_sor_nr
(
struct
drm_device
*
dev
)
{
struct
nouveau_device
*
device
=
nouveau_dev
(
dev
);
if
(
device
->
chipset
<
0x90
||
device
->
chipset
==
0x92
||
device
->
chipset
==
0xa0
)
return
2
;
return
4
;
}
u32
nv50_display_active_crtcs
(
struct
drm_device
*
dev
)
{
struct
nouveau_device
*
device
=
nouveau_dev
(
dev
);
u32
mask
=
0
;
int
i
;
if
(
device
->
chipset
<
0x90
||
device
->
chipset
==
0x92
||
device
->
chipset
==
0xa0
)
{
for
(
i
=
0
;
i
<
2
;
i
++
)
mask
|=
nv_rd32
(
device
,
NV50_PDISPLAY_SOR_MODE_CTRL_C
(
i
));
}
else
{
for
(
i
=
0
;
i
<
4
;
i
++
)
mask
|=
nv_rd32
(
device
,
NV90_PDISPLAY_SOR_MODE_CTRL_C
(
i
));
}
for
(
i
=
0
;
i
<
3
;
i
++
)
mask
|=
nv_rd32
(
device
,
NV50_PDISPLAY_DAC_MODE_CTRL_C
(
i
));
return
mask
&
3
;
}
int
nv50_display_early_init
(
struct
drm_device
*
dev
)
{
return
0
;
}
void
nv50_display_late_takedown
(
struct
drm_device
*
dev
)
{
}
int
nv50_display_sync
(
struct
drm_device
*
dev
)
{
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
struct
nouveau_channel
*
evo
=
disp
->
master
;
int
ret
;
ret
=
RING_SPACE
(
evo
,
6
);
if
(
ret
==
0
)
{
BEGIN_NV04
(
evo
,
0
,
0x0084
,
1
);
OUT_RING
(
evo
,
0x80000000
);
BEGIN_NV04
(
evo
,
0
,
0x0080
,
1
);
OUT_RING
(
evo
,
0
);
BEGIN_NV04
(
evo
,
0
,
0x0084
,
1
);
OUT_RING
(
evo
,
0x00000000
);
nv_wo32
(
disp
->
ramin
,
0x2000
,
0x00000000
);
FIRE_RING
(
evo
);
if
(
nv_wait_ne
(
disp
->
ramin
,
0x2000
,
0xffffffff
,
0x00000000
))
return
0
;
}
return
0
;
}
int
nv50_display_init
(
struct
drm_device
*
dev
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_device
*
device
=
nouveau_dev
(
dev
);
struct
nouveau_channel
*
evo
;
int
ret
,
i
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
nv_wr32
(
device
,
NV50_PDISPLAY_DAC_DPMS_CTRL
(
i
),
0x00550000
|
NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING
);
nv_wr32
(
device
,
NV50_PDISPLAY_DAC_CLK_CTRL1
(
i
),
0x00000001
);
}
for
(
i
=
0
;
i
<
2
;
i
++
)
{
nv_wr32
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
),
0x2000
);
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
),
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS
,
0
))
{
NV_ERROR
(
drm
,
"timeout: CURSOR_CTRL2_STATUS == 0
\n
"
);
NV_ERROR
(
drm
,
"CURSOR_CTRL2 = 0x%08x
\n
"
,
nv_rd32
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
)));
return
-
EBUSY
;
}
nv_wr32
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
),
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON
);
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
),
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE
))
{
NV_ERROR
(
drm
,
"timeout: "
"CURSOR_CTRL2_STATUS_ACTIVE(%d)
\n
"
,
i
);
NV_ERROR
(
drm
,
"CURSOR_CTRL2(%d) = 0x%08x
\n
"
,
i
,
nv_rd32
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
)));
return
-
EBUSY
;
}
}
ret
=
nv50_evo_init
(
dev
);
if
(
ret
)
return
ret
;
evo
=
nv50_display
(
dev
)
->
master
;
ret
=
RING_SPACE
(
evo
,
3
);
if
(
ret
)
return
ret
;
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UNK84
,
2
);
OUT_RING
(
evo
,
NV50_EVO_UNK84_NOTIFY_DISABLED
);
OUT_RING
(
evo
,
NvEvoSync
);
return
nv50_display_sync
(
dev
);
}
void
nv50_display_fini
(
struct
drm_device
*
dev
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_device
*
device
=
nouveau_dev
(
dev
);
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
struct
nouveau_channel
*
evo
=
disp
->
master
;
struct
drm_crtc
*
drm_crtc
;
int
ret
,
i
;
list_for_each_entry
(
drm_crtc
,
&
dev
->
mode_config
.
crtc_list
,
head
)
{
struct
nouveau_crtc
*
crtc
=
nouveau_crtc
(
drm_crtc
);
nv50_crtc_blank
(
crtc
,
true
);
}
ret
=
RING_SPACE
(
evo
,
2
);
if
(
ret
==
0
)
{
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
}
FIRE_RING
(
evo
);
/* Almost like ack'ing a vblank interrupt, maybe in the spirit of
* cleaning up?
*/
list_for_each_entry
(
drm_crtc
,
&
dev
->
mode_config
.
crtc_list
,
head
)
{
struct
nouveau_crtc
*
crtc
=
nouveau_crtc
(
drm_crtc
);
uint32_t
mask
=
NV50_PDISPLAY_INTR_1_VBLANK_CRTC_
(
crtc
->
index
);
if
(
!
crtc
->
base
.
enabled
)
continue
;
nv_wr32
(
device
,
NV50_PDISPLAY_INTR_1
,
mask
);
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_INTR_1
,
mask
,
mask
))
{
NV_ERROR
(
drm
,
"timeout: (0x610024 & 0x%08x) == "
"0x%08x
\n
"
,
mask
,
mask
);
NV_ERROR
(
drm
,
"0x610024 = 0x%08x
\n
"
,
nv_rd32
(
device
,
NV50_PDISPLAY_INTR_1
));
}
}
for
(
i
=
0
;
i
<
2
;
i
++
)
{
nv_wr32
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
),
0
);
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
),
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS
,
0
))
{
NV_ERROR
(
drm
,
"timeout: CURSOR_CTRL2_STATUS == 0
\n
"
);
NV_ERROR
(
drm
,
"CURSOR_CTRL2 = 0x%08x
\n
"
,
nv_rd32
(
device
,
NV50_PDISPLAY_CURSOR_CURSOR_CTRL2
(
i
)));
}
}
nv50_evo_fini
(
dev
);
for
(
i
=
0
;
i
<
3
;
i
++
)
{
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_SOR_DPMS_STATE
(
i
),
NV50_PDISPLAY_SOR_DPMS_STATE_WAIT
,
0
))
{
NV_ERROR
(
drm
,
"timeout: SOR_DPMS_STATE_WAIT(%d) == 0
\n
"
,
i
);
NV_ERROR
(
drm
,
"SOR_DPMS_STATE(%d) = 0x%08x
\n
"
,
i
,
nv_rd32
(
device
,
NV50_PDISPLAY_SOR_DPMS_STATE
(
i
)));
}
}
}
int
nv50_display_create
(
struct
drm_device
*
dev
)
{
static
const
u16
oclass
[]
=
{
NVA3_DISP_CLASS
,
NV94_DISP_CLASS
,
NVA0_DISP_CLASS
,
NV84_DISP_CLASS
,
NV50_DISP_CLASS
,
};
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
dcb_table
*
dcb
=
&
drm
->
vbios
.
dcb
;
struct
drm_connector
*
connector
,
*
ct
;
struct
nv50_display
*
priv
;
int
ret
,
i
;
priv
=
kzalloc
(
sizeof
(
*
priv
),
GFP_KERNEL
);
if
(
!
priv
)
return
-
ENOMEM
;
nouveau_display
(
dev
)
->
priv
=
priv
;
nouveau_display
(
dev
)
->
dtor
=
nv50_display_destroy
;
nouveau_display
(
dev
)
->
init
=
nv50_display_init
;
nouveau_display
(
dev
)
->
fini
=
nv50_display_fini
;
/* attempt to allocate a supported evo display class */
ret
=
-
ENODEV
;
for
(
i
=
0
;
ret
&&
i
<
ARRAY_SIZE
(
oclass
);
i
++
)
{
ret
=
nouveau_object_new
(
nv_object
(
drm
),
NVDRM_DEVICE
,
0xd1500000
,
oclass
[
i
],
NULL
,
0
,
&
priv
->
core
);
}
if
(
ret
)
return
ret
;
/* Create CRTC objects */
for
(
i
=
0
;
i
<
2
;
i
++
)
{
ret
=
nv50_crtc_create
(
dev
,
i
);
if
(
ret
)
return
ret
;
}
/* We setup the encoders from the BIOS table */
for
(
i
=
0
;
i
<
dcb
->
entries
;
i
++
)
{
struct
dcb_output
*
entry
=
&
dcb
->
entry
[
i
];
if
(
entry
->
location
!=
DCB_LOC_ON_CHIP
)
{
NV_WARN
(
drm
,
"Off-chip encoder %d/%d unsupported
\n
"
,
entry
->
type
,
ffs
(
entry
->
or
)
-
1
);
continue
;
}
connector
=
nouveau_connector_create
(
dev
,
entry
->
connector
);
if
(
IS_ERR
(
connector
))
continue
;
switch
(
entry
->
type
)
{
case
DCB_OUTPUT_TMDS
:
case
DCB_OUTPUT_LVDS
:
case
DCB_OUTPUT_DP
:
nv50_sor_create
(
connector
,
entry
);
break
;
case
DCB_OUTPUT_ANALOG
:
nv50_dac_create
(
connector
,
entry
);
break
;
default:
NV_WARN
(
drm
,
"DCB encoder %d unknown
\n
"
,
entry
->
type
);
continue
;
}
}
list_for_each_entry_safe
(
connector
,
ct
,
&
dev
->
mode_config
.
connector_list
,
head
)
{
if
(
!
connector
->
encoder_ids
[
0
])
{
NV_WARN
(
drm
,
"%s has no encoders, removing
\n
"
,
drm_get_connector_name
(
connector
));
connector
->
funcs
->
destroy
(
connector
);
}
}
ret
=
nv50_evo_create
(
dev
);
if
(
ret
)
{
nv50_display_destroy
(
dev
);
return
ret
;
}
return
0
;
}
void
nv50_display_destroy
(
struct
drm_device
*
dev
)
{
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
nv50_evo_destroy
(
dev
);
kfree
(
disp
);
}
struct
nouveau_bo
*
nv50_display_crtc_sema
(
struct
drm_device
*
dev
,
int
crtc
)
{
return
nv50_display
(
dev
)
->
crtc
[
crtc
].
sem
.
bo
;
}
void
nv50_display_flip_stop
(
struct
drm_crtc
*
crtc
)
{
struct
nv50_display
*
disp
=
nv50_display
(
crtc
->
dev
);
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
struct
nv50_display_crtc
*
dispc
=
&
disp
->
crtc
[
nv_crtc
->
index
];
struct
nouveau_channel
*
evo
=
dispc
->
sync
;
int
ret
;
ret
=
RING_SPACE
(
evo
,
8
);
if
(
ret
)
{
WARN_ON
(
1
);
return
;
}
BEGIN_NV04
(
evo
,
0
,
0x0084
,
1
);
OUT_RING
(
evo
,
0x00000000
);
BEGIN_NV04
(
evo
,
0
,
0x0094
,
1
);
OUT_RING
(
evo
,
0x00000000
);
BEGIN_NV04
(
evo
,
0
,
0x00c0
,
1
);
OUT_RING
(
evo
,
0x00000000
);
BEGIN_NV04
(
evo
,
0
,
0x0080
,
1
);
OUT_RING
(
evo
,
0x00000000
);
FIRE_RING
(
evo
);
}
int
nv50_display_flip_next
(
struct
drm_crtc
*
crtc
,
struct
drm_framebuffer
*
fb
,
struct
nouveau_channel
*
chan
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
crtc
->
dev
);
struct
nouveau_framebuffer
*
nv_fb
=
nouveau_framebuffer
(
fb
);
struct
nv50_display
*
disp
=
nv50_display
(
crtc
->
dev
);
struct
nouveau_crtc
*
nv_crtc
=
nouveau_crtc
(
crtc
);
struct
nv50_display_crtc
*
dispc
=
&
disp
->
crtc
[
nv_crtc
->
index
];
struct
nouveau_channel
*
evo
=
dispc
->
sync
;
int
ret
;
ret
=
RING_SPACE
(
evo
,
chan
?
25
:
27
);
if
(
unlikely
(
ret
))
return
ret
;
/* synchronise with the rendering channel, if necessary */
if
(
likely
(
chan
))
{
ret
=
RING_SPACE
(
chan
,
10
);
if
(
ret
)
{
WIND_RING
(
evo
);
return
ret
;
}
if
(
nv_device
(
drm
->
device
)
->
chipset
<
0xc0
)
{
BEGIN_NV04
(
chan
,
0
,
0x0060
,
2
);
OUT_RING
(
chan
,
NvEvoSema0
+
nv_crtc
->
index
);
OUT_RING
(
chan
,
dispc
->
sem
.
offset
);
BEGIN_NV04
(
chan
,
0
,
0x006c
,
1
);
OUT_RING
(
chan
,
0xf00d0000
|
dispc
->
sem
.
value
);
BEGIN_NV04
(
chan
,
0
,
0x0064
,
2
);
OUT_RING
(
chan
,
dispc
->
sem
.
offset
^
0x10
);
OUT_RING
(
chan
,
0x74b1e000
);
BEGIN_NV04
(
chan
,
0
,
0x0060
,
1
);
if
(
nv_device
(
drm
->
device
)
->
chipset
<
0x84
)
OUT_RING
(
chan
,
NvSema
);
else
OUT_RING
(
chan
,
chan
->
vram
);
}
else
{
u64
offset
=
nvc0_fence_crtc
(
chan
,
nv_crtc
->
index
);
offset
+=
dispc
->
sem
.
offset
;
BEGIN_NVC0
(
chan
,
0
,
0x0010
,
4
);
OUT_RING
(
chan
,
upper_32_bits
(
offset
));
OUT_RING
(
chan
,
lower_32_bits
(
offset
));
OUT_RING
(
chan
,
0xf00d0000
|
dispc
->
sem
.
value
);
OUT_RING
(
chan
,
0x1002
);
BEGIN_NVC0
(
chan
,
0
,
0x0010
,
4
);
OUT_RING
(
chan
,
upper_32_bits
(
offset
));
OUT_RING
(
chan
,
lower_32_bits
(
offset
^
0x10
));
OUT_RING
(
chan
,
0x74b1e000
);
OUT_RING
(
chan
,
0x1001
);
}
FIRE_RING
(
chan
);
}
else
{
nouveau_bo_wr32
(
dispc
->
sem
.
bo
,
dispc
->
sem
.
offset
/
4
,
0xf00d0000
|
dispc
->
sem
.
value
);
}
/* queue the flip on the crtc's "display sync" channel */
BEGIN_NV04
(
evo
,
0
,
0x0100
,
1
);
OUT_RING
(
evo
,
0xfffe0000
);
if
(
chan
)
{
BEGIN_NV04
(
evo
,
0
,
0x0084
,
1
);
OUT_RING
(
evo
,
0x00000100
);
}
else
{
BEGIN_NV04
(
evo
,
0
,
0x0084
,
1
);
OUT_RING
(
evo
,
0x00000010
);
/* allows gamma somehow, PDISP will bitch at you if
* you don't wait for vblank before changing this..
*/
BEGIN_NV04
(
evo
,
0
,
0x00e0
,
1
);
OUT_RING
(
evo
,
0x40000000
);
}
BEGIN_NV04
(
evo
,
0
,
0x0088
,
4
);
OUT_RING
(
evo
,
dispc
->
sem
.
offset
);
OUT_RING
(
evo
,
0xf00d0000
|
dispc
->
sem
.
value
);
OUT_RING
(
evo
,
0x74b1e000
);
OUT_RING
(
evo
,
NvEvoSync
);
BEGIN_NV04
(
evo
,
0
,
0x00a0
,
2
);
OUT_RING
(
evo
,
0x00000000
);
OUT_RING
(
evo
,
0x00000000
);
BEGIN_NV04
(
evo
,
0
,
0x00c0
,
1
);
OUT_RING
(
evo
,
nv_fb
->
r_dma
);
BEGIN_NV04
(
evo
,
0
,
0x0110
,
2
);
OUT_RING
(
evo
,
0x00000000
);
OUT_RING
(
evo
,
0x00000000
);
BEGIN_NV04
(
evo
,
0
,
0x0800
,
5
);
OUT_RING
(
evo
,
nv_fb
->
nvbo
->
bo
.
offset
>>
8
);
OUT_RING
(
evo
,
0
);
OUT_RING
(
evo
,
(
fb
->
height
<<
16
)
|
fb
->
width
);
OUT_RING
(
evo
,
nv_fb
->
r_pitch
);
OUT_RING
(
evo
,
nv_fb
->
r_format
);
BEGIN_NV04
(
evo
,
0
,
0x0080
,
1
);
OUT_RING
(
evo
,
0x00000000
);
FIRE_RING
(
evo
);
dispc
->
sem
.
offset
^=
0x10
;
dispc
->
sem
.
value
++
;
return
0
;
}
drivers/gpu/drm/nouveau/nv50_display.h
浏览文件 @
4f6029da
...
...
@@ -30,65 +30,6 @@
#include "nouveau_display.h"
#include "nouveau_crtc.h"
#include "nouveau_reg.h"
#include "nv50_evo.h"
struct
nv50_display_crtc
{
struct
nouveau_channel
*
sync
;
struct
{
struct
nouveau_bo
*
bo
;
u32
offset
;
u16
value
;
}
sem
;
};
struct
nv50_display
{
struct
nouveau_channel
*
master
;
struct
nouveau_object
*
core
;
struct
nouveau_gpuobj
*
ramin
;
u32
dmao
;
u32
hash
;
struct
nv50_display_crtc
crtc
[
2
];
struct
tasklet_struct
tasklet
;
struct
{
struct
dcb_output
*
dcb
;
u16
script
;
u32
pclk
;
}
irq
;
};
static
inline
struct
nv50_display
*
nv50_display
(
struct
drm_device
*
dev
)
{
return
nouveau_display
(
dev
)
->
priv
;
}
int
nv50_display_early_init
(
struct
drm_device
*
dev
);
void
nv50_display_late_takedown
(
struct
drm_device
*
dev
);
int
nv50_display_create
(
struct
drm_device
*
dev
);
int
nv50_display_init
(
struct
drm_device
*
dev
);
void
nv50_display_fini
(
struct
drm_device
*
dev
);
void
nv50_display_destroy
(
struct
drm_device
*
dev
);
int
nv50_crtc_blank
(
struct
nouveau_crtc
*
,
bool
blank
);
int
nv50_crtc_set_clock
(
struct
drm_device
*
,
int
head
,
int
pclk
);
u32
nv50_display_active_crtcs
(
struct
drm_device
*
);
int
nv50_display_sync
(
struct
drm_device
*
);
int
nv50_display_flip_next
(
struct
drm_crtc
*
,
struct
drm_framebuffer
*
,
struct
nouveau_channel
*
chan
);
void
nv50_display_flip_stop
(
struct
drm_crtc
*
);
int
nv50_evo_create
(
struct
drm_device
*
dev
);
void
nv50_evo_destroy
(
struct
drm_device
*
dev
);
int
nv50_evo_init
(
struct
drm_device
*
dev
);
void
nv50_evo_fini
(
struct
drm_device
*
dev
);
void
nv50_evo_dmaobj_init
(
struct
nouveau_gpuobj
*
,
u32
memtype
,
u64
base
,
u64
size
);
int
nv50_evo_dmaobj_new
(
struct
nouveau_channel
*
,
u32
handle
,
u32
memtype
,
u64
base
,
u64
size
,
struct
nouveau_gpuobj
**
);
int
nvd0_display_create
(
struct
drm_device
*
);
void
nvd0_display_destroy
(
struct
drm_device
*
);
...
...
@@ -99,7 +40,6 @@ void nvd0_display_flip_stop(struct drm_crtc *);
int
nvd0_display_flip_next
(
struct
drm_crtc
*
,
struct
drm_framebuffer
*
,
struct
nouveau_channel
*
,
u32
swap_interval
);
struct
nouveau_bo
*
nv50_display_crtc_sema
(
struct
drm_device
*
,
int
head
);
struct
nouveau_bo
*
nvd0_display_crtc_sema
(
struct
drm_device
*
,
int
head
);
#endif
/* __NV50_DISPLAY_H__ */
drivers/gpu/drm/nouveau/nv50_evo.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright 2010 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
*/
#include <drm/drmP.h>
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nv50_display.h"
#include <core/gpuobj.h>
#include <subdev/timer.h>
#include <subdev/fb.h>
static
u32
nv50_evo_rd32
(
struct
nouveau_object
*
object
,
u64
addr
)
{
void
__iomem
*
iomem
=
object
->
oclass
->
ofuncs
->
rd08
;
return
ioread32_native
(
iomem
+
addr
);
}
static
void
nv50_evo_wr32
(
struct
nouveau_object
*
object
,
u64
addr
,
u32
data
)
{
void
__iomem
*
iomem
=
object
->
oclass
->
ofuncs
->
rd08
;
iowrite32_native
(
data
,
iomem
+
addr
);
}
static
void
nv50_evo_channel_del
(
struct
nouveau_channel
**
pevo
)
{
struct
nouveau_channel
*
evo
=
*
pevo
;
if
(
!
evo
)
return
;
*
pevo
=
NULL
;
nouveau_bo_unmap
(
evo
->
push
.
buffer
);
nouveau_bo_ref
(
NULL
,
&
evo
->
push
.
buffer
);
if
(
evo
->
object
)
iounmap
(
evo
->
object
->
oclass
->
ofuncs
);
kfree
(
evo
);
}
int
nv50_evo_dmaobj_new
(
struct
nouveau_channel
*
evo
,
u32
handle
,
u32
memtype
,
u64
base
,
u64
size
,
struct
nouveau_gpuobj
**
pobj
)
{
struct
drm_device
*
dev
=
evo
->
fence
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
u32
dmao
=
disp
->
dmao
;
u32
hash
=
disp
->
hash
;
u32
flags5
;
if
(
nv_device
(
drm
->
device
)
->
chipset
<
0xc0
)
{
/* not supported on 0x50, specified in format mthd */
if
(
nv_device
(
drm
->
device
)
->
chipset
==
0x50
)
memtype
=
0
;
flags5
=
0x00010000
;
}
else
{
if
(
memtype
&
0x80000000
)
flags5
=
0x00000000
;
/* large pages */
else
flags5
=
0x00020000
;
}
nv_wo32
(
disp
->
ramin
,
dmao
+
0x00
,
0x0019003d
|
(
memtype
<<
22
));
nv_wo32
(
disp
->
ramin
,
dmao
+
0x04
,
lower_32_bits
(
base
+
size
-
1
));
nv_wo32
(
disp
->
ramin
,
dmao
+
0x08
,
lower_32_bits
(
base
));
nv_wo32
(
disp
->
ramin
,
dmao
+
0x0c
,
upper_32_bits
(
base
+
size
-
1
)
<<
24
|
upper_32_bits
(
base
));
nv_wo32
(
disp
->
ramin
,
dmao
+
0x10
,
0x00000000
);
nv_wo32
(
disp
->
ramin
,
dmao
+
0x14
,
flags5
);
nv_wo32
(
disp
->
ramin
,
hash
+
0x00
,
handle
);
nv_wo32
(
disp
->
ramin
,
hash
+
0x04
,
(
evo
->
handle
<<
28
)
|
(
dmao
<<
10
)
|
evo
->
handle
);
disp
->
dmao
+=
0x20
;
disp
->
hash
+=
0x08
;
return
0
;
}
static
int
nv50_evo_channel_new
(
struct
drm_device
*
dev
,
int
chid
,
struct
nouveau_channel
**
pevo
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
struct
nouveau_channel
*
evo
;
int
ret
;
evo
=
kzalloc
(
sizeof
(
struct
nouveau_channel
),
GFP_KERNEL
);
if
(
!
evo
)
return
-
ENOMEM
;
*
pevo
=
evo
;
evo
->
drm
=
drm
;
evo
->
handle
=
chid
;
evo
->
fence
=
dev
;
evo
->
user_get
=
4
;
evo
->
user_put
=
0
;
ret
=
nouveau_bo_new
(
dev
,
4096
,
0
,
TTM_PL_FLAG_VRAM
,
0
,
0
,
NULL
,
&
evo
->
push
.
buffer
);
if
(
ret
==
0
)
ret
=
nouveau_bo_pin
(
evo
->
push
.
buffer
,
TTM_PL_FLAG_VRAM
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"Error creating EVO DMA push buffer: %d
\n
"
,
ret
);
nv50_evo_channel_del
(
pevo
);
return
ret
;
}
ret
=
nouveau_bo_map
(
evo
->
push
.
buffer
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"Error mapping EVO DMA push buffer: %d
\n
"
,
ret
);
nv50_evo_channel_del
(
pevo
);
return
ret
;
}
evo
->
object
=
kzalloc
(
sizeof
(
*
evo
->
object
),
GFP_KERNEL
);
#ifdef NOUVEAU_OBJECT_MAGIC
evo
->
object
->
_magic
=
NOUVEAU_OBJECT_MAGIC
;
#endif
evo
->
object
->
parent
=
nv_object
(
disp
->
ramin
)
->
parent
;
evo
->
object
->
engine
=
nv_object
(
disp
->
ramin
)
->
engine
;
evo
->
object
->
oclass
=
kzalloc
(
sizeof
(
*
evo
->
object
->
oclass
),
GFP_KERNEL
);
evo
->
object
->
oclass
->
ofuncs
=
kzalloc
(
sizeof
(
*
evo
->
object
->
oclass
->
ofuncs
),
GFP_KERNEL
);
evo
->
object
->
oclass
->
ofuncs
->
rd32
=
nv50_evo_rd32
;
evo
->
object
->
oclass
->
ofuncs
->
wr32
=
nv50_evo_wr32
;
evo
->
object
->
oclass
->
ofuncs
->
rd08
=
ioremap
(
pci_resource_start
(
dev
->
pdev
,
0
)
+
NV50_PDISPLAY_USER
(
evo
->
handle
),
PAGE_SIZE
);
return
0
;
}
static
int
nv50_evo_channel_init
(
struct
nouveau_channel
*
evo
)
{
struct
nouveau_drm
*
drm
=
evo
->
drm
;
struct
nouveau_device
*
device
=
nv_device
(
drm
->
device
);
int
id
=
evo
->
handle
,
ret
,
i
;
u64
pushbuf
=
evo
->
push
.
buffer
->
bo
.
offset
;
u32
tmp
;
tmp
=
nv_rd32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
));
if
((
tmp
&
0x009f0000
)
==
0x00020000
)
nv_wr32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
tmp
|
0x00800000
);
tmp
=
nv_rd32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
));
if
((
tmp
&
0x003f0000
)
==
0x00030000
)
nv_wr32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
tmp
|
0x00600000
);
/* initialise fifo */
nv_wr32
(
device
,
NV50_PDISPLAY_EVO_DMA_CB
(
id
),
pushbuf
>>
8
|
NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM
|
NV50_PDISPLAY_EVO_DMA_CB_VALID
);
nv_wr32
(
device
,
NV50_PDISPLAY_EVO_UNK2
(
id
),
0x00010000
);
nv_wr32
(
device
,
NV50_PDISPLAY_EVO_HASH_TAG
(
id
),
id
);
nv_mask
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
NV50_PDISPLAY_EVO_CTRL_DMA
,
NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED
);
nv_wr32
(
device
,
NV50_PDISPLAY_USER_PUT
(
id
),
0x00000000
);
nv_wr32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
0x01000003
|
NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED
);
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
0x80000000
,
0x00000000
))
{
NV_ERROR
(
drm
,
"EvoCh %d init timeout: 0x%08x
\n
"
,
id
,
nv_rd32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
)));
return
-
EBUSY
;
}
/* enable error reporting on the channel */
nv_mask
(
device
,
0x610028
,
0x00000000
,
0x00010001
<<
id
);
evo
->
dma
.
max
=
(
4096
/
4
)
-
2
;
evo
->
dma
.
max
&=
~
7
;
evo
->
dma
.
put
=
0
;
evo
->
dma
.
cur
=
evo
->
dma
.
put
;
evo
->
dma
.
free
=
evo
->
dma
.
max
-
evo
->
dma
.
cur
;
ret
=
RING_SPACE
(
evo
,
NOUVEAU_DMA_SKIPS
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
NOUVEAU_DMA_SKIPS
;
i
++
)
OUT_RING
(
evo
,
0
);
return
0
;
}
static
void
nv50_evo_channel_fini
(
struct
nouveau_channel
*
evo
)
{
struct
nouveau_drm
*
drm
=
evo
->
drm
;
struct
nouveau_device
*
device
=
nv_device
(
drm
->
device
);
int
id
=
evo
->
handle
;
nv_mask
(
device
,
0x610028
,
0x00010001
<<
id
,
0x00000000
);
nv_mask
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
0x00001010
,
0x00001000
);
nv_wr32
(
device
,
NV50_PDISPLAY_INTR_0
,
(
1
<<
id
));
nv_mask
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
0x00000003
,
0x00000000
);
if
(
!
nv_wait
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
),
0x001e0000
,
0x00000000
))
{
NV_ERROR
(
drm
,
"EvoCh %d takedown timeout: 0x%08x
\n
"
,
id
,
nv_rd32
(
device
,
NV50_PDISPLAY_EVO_CTRL
(
id
)));
}
}
void
nv50_evo_destroy
(
struct
drm_device
*
dev
)
{
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
int
i
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
disp
->
crtc
[
i
].
sem
.
bo
)
{
nouveau_bo_unmap
(
disp
->
crtc
[
i
].
sem
.
bo
);
nouveau_bo_ref
(
NULL
,
&
disp
->
crtc
[
i
].
sem
.
bo
);
}
nv50_evo_channel_del
(
&
disp
->
crtc
[
i
].
sync
);
}
nv50_evo_channel_del
(
&
disp
->
master
);
}
int
nv50_evo_create
(
struct
drm_device
*
dev
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_fb
*
pfb
=
nouveau_fb
(
drm
->
device
);
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
struct
nouveau_channel
*
evo
;
int
ret
,
i
,
j
;
/* setup object management on it, any other evo channel will
* use this also as there's no per-channel support on the
* hardware
*/
disp
->
ramin
=
nv_gpuobj
(
disp
->
core
->
parent
);
disp
->
hash
=
0x0000
;
disp
->
dmao
=
0x1000
;
/* create primary evo channel, the one we use for modesetting
* purporses
*/
ret
=
nv50_evo_channel_new
(
dev
,
0
,
&
disp
->
master
);
if
(
ret
)
return
ret
;
evo
=
disp
->
master
;
ret
=
nv50_evo_dmaobj_new
(
disp
->
master
,
NvEvoSync
,
0x0000
,
disp
->
ramin
->
addr
+
0x2000
,
0x1000
,
NULL
);
if
(
ret
)
goto
err
;
/* create some default objects for the scanout memtypes we support */
ret
=
nv50_evo_dmaobj_new
(
disp
->
master
,
NvEvoVRAM
,
0x0000
,
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
disp
->
master
,
NvEvoVRAM_LP
,
0x80000000
,
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
disp
->
master
,
NvEvoFB32
,
0x80000000
|
(
nv_device
(
drm
->
device
)
->
chipset
<
0xc0
?
0x7a
:
0xfe
),
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
disp
->
master
,
NvEvoFB16
,
0x80000000
|
(
nv_device
(
drm
->
device
)
->
chipset
<
0xc0
?
0x70
:
0xfe
),
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
/* create "display sync" channels and other structures we need
* to implement page flipping
*/
for
(
i
=
0
;
i
<
2
;
i
++
)
{
struct
nv50_display_crtc
*
dispc
=
&
disp
->
crtc
[
i
];
u64
offset
;
ret
=
nv50_evo_channel_new
(
dev
,
1
+
i
,
&
dispc
->
sync
);
if
(
ret
)
goto
err
;
ret
=
nouveau_bo_new
(
dev
,
4096
,
0x1000
,
TTM_PL_FLAG_VRAM
,
0
,
0x0000
,
NULL
,
&
dispc
->
sem
.
bo
);
if
(
!
ret
)
{
ret
=
nouveau_bo_pin
(
dispc
->
sem
.
bo
,
TTM_PL_FLAG_VRAM
);
if
(
!
ret
)
ret
=
nouveau_bo_map
(
dispc
->
sem
.
bo
);
if
(
ret
)
nouveau_bo_ref
(
NULL
,
&
dispc
->
sem
.
bo
);
offset
=
dispc
->
sem
.
bo
->
bo
.
offset
;
}
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
dispc
->
sync
,
NvEvoSync
,
0x0000
,
offset
,
4096
,
NULL
);
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
dispc
->
sync
,
NvEvoVRAM_LP
,
0x80000000
,
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
dispc
->
sync
,
NvEvoFB32
,
0x80000000
|
(
nv_device
(
drm
->
device
)
->
chipset
<
0xc0
?
0x7a
:
0xfe
),
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
ret
=
nv50_evo_dmaobj_new
(
dispc
->
sync
,
NvEvoFB16
,
0x80000000
|
(
nv_device
(
drm
->
device
)
->
chipset
<
0xc0
?
0x70
:
0xfe
),
0
,
pfb
->
ram
.
size
,
NULL
);
if
(
ret
)
goto
err
;
for
(
j
=
0
;
j
<
4096
;
j
+=
4
)
nouveau_bo_wr32
(
dispc
->
sem
.
bo
,
j
/
4
,
0x74b1e000
);
dispc
->
sem
.
offset
=
0
;
}
return
0
;
err:
nv50_evo_destroy
(
dev
);
return
ret
;
}
int
nv50_evo_init
(
struct
drm_device
*
dev
)
{
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
int
ret
,
i
;
ret
=
nv50_evo_channel_init
(
disp
->
master
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
ret
=
nv50_evo_channel_init
(
disp
->
crtc
[
i
].
sync
);
if
(
ret
)
return
ret
;
}
return
0
;
}
void
nv50_evo_fini
(
struct
drm_device
*
dev
)
{
struct
nv50_display
*
disp
=
nv50_display
(
dev
);
int
i
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
disp
->
crtc
[
i
].
sync
)
nv50_evo_channel_fini
(
disp
->
crtc
[
i
].
sync
);
}
if
(
disp
->
master
)
nv50_evo_channel_fini
(
disp
->
master
);
}
drivers/gpu/drm/nouveau/nv50_evo.h
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#ifndef __NV50_EVO_H__
#define __NV50_EVO_H__
#define NV50_EVO_UPDATE 0x00000080
#define NV50_EVO_UNK84 0x00000084
#define NV50_EVO_UNK84_NOTIFY 0x40000000
#define NV50_EVO_UNK84_NOTIFY_DISABLED 0x00000000
#define NV50_EVO_UNK84_NOTIFY_ENABLED 0x40000000
#define NV50_EVO_DMA_NOTIFY 0x00000088
#define NV50_EVO_DMA_NOTIFY_HANDLE 0xffffffff
#define NV50_EVO_DMA_NOTIFY_HANDLE_NONE 0x00000000
#define NV50_EVO_UNK8C 0x0000008C
#define NV50_EVO_DAC(n, r) ((n) * 0x80 + NV50_EVO_DAC_##r)
#define NV50_EVO_DAC_MODE_CTRL 0x00000400
#define NV50_EVO_DAC_MODE_CTRL_CRTC0 0x00000001
#define NV50_EVO_DAC_MODE_CTRL_CRTC1 0x00000002
#define NV50_EVO_DAC_MODE_CTRL2 0x00000404
#define NV50_EVO_DAC_MODE_CTRL2_NHSYNC 0x00000001
#define NV50_EVO_DAC_MODE_CTRL2_NVSYNC 0x00000002
#define NV50_EVO_SOR(n, r) ((n) * 0x40 + NV50_EVO_SOR_##r)
#define NV50_EVO_SOR_MODE_CTRL 0x00000600
#define NV50_EVO_SOR_MODE_CTRL_CRTC0 0x00000001
#define NV50_EVO_SOR_MODE_CTRL_CRTC1 0x00000002
#define NV50_EVO_SOR_MODE_CTRL_TMDS 0x00000100
#define NV50_EVO_SOR_MODE_CTRL_TMDS_DUAL_LINK 0x00000400
#define NV50_EVO_SOR_MODE_CTRL_NHSYNC 0x00001000
#define NV50_EVO_SOR_MODE_CTRL_NVSYNC 0x00002000
#define NV50_EVO_CRTC(n, r) ((n) * 0x400 + NV50_EVO_CRTC_##r)
#define NV84_EVO_CRTC(n, r) ((n) * 0x400 + NV84_EVO_CRTC_##r)
#define NV50_EVO_CRTC_UNK0800 0x00000800
#define NV50_EVO_CRTC_CLOCK 0x00000804
#define NV50_EVO_CRTC_INTERLACE 0x00000808
#define NV50_EVO_CRTC_DISPLAY_START 0x00000810
#define NV50_EVO_CRTC_DISPLAY_TOTAL 0x00000814
#define NV50_EVO_CRTC_SYNC_DURATION 0x00000818
#define NV50_EVO_CRTC_SYNC_START_TO_BLANK_END 0x0000081c
#define NV50_EVO_CRTC_UNK0820 0x00000820
#define NV50_EVO_CRTC_UNK0824 0x00000824
#define NV50_EVO_CRTC_UNK082C 0x0000082c
#define NV50_EVO_CRTC_CLUT_MODE 0x00000840
/* You can't have a palette in 8 bit mode (=OFF) */
#define NV50_EVO_CRTC_CLUT_MODE_BLANK 0x00000000
#define NV50_EVO_CRTC_CLUT_MODE_OFF 0x80000000
#define NV50_EVO_CRTC_CLUT_MODE_ON 0xC0000000
#define NV50_EVO_CRTC_CLUT_OFFSET 0x00000844
#define NV84_EVO_CRTC_CLUT_DMA 0x0000085C
#define NV84_EVO_CRTC_CLUT_DMA_HANDLE 0xffffffff
#define NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE 0x00000000
#define NV50_EVO_CRTC_FB_OFFSET 0x00000860
#define NV50_EVO_CRTC_FB_SIZE 0x00000868
#define NV50_EVO_CRTC_FB_CONFIG 0x0000086c
#define NV50_EVO_CRTC_FB_CONFIG_MODE 0x00100000
#define NV50_EVO_CRTC_FB_CONFIG_MODE_TILE 0x00000000
#define NV50_EVO_CRTC_FB_CONFIG_MODE_PITCH 0x00100000
#define NV50_EVO_CRTC_FB_DEPTH 0x00000870
#define NV50_EVO_CRTC_FB_DEPTH_8 0x00001e00
#define NV50_EVO_CRTC_FB_DEPTH_15 0x0000e900
#define NV50_EVO_CRTC_FB_DEPTH_16 0x0000e800
#define NV50_EVO_CRTC_FB_DEPTH_24 0x0000cf00
#define NV50_EVO_CRTC_FB_DEPTH_30 0x0000d100
#define NV50_EVO_CRTC_FB_DMA 0x00000874
#define NV50_EVO_CRTC_FB_DMA_HANDLE 0xffffffff
#define NV50_EVO_CRTC_FB_DMA_HANDLE_NONE 0x00000000
#define NV50_EVO_CRTC_CURSOR_CTRL 0x00000880
#define NV50_EVO_CRTC_CURSOR_CTRL_HIDE 0x05000000
#define NV50_EVO_CRTC_CURSOR_CTRL_SHOW 0x85000000
#define NV50_EVO_CRTC_CURSOR_OFFSET 0x00000884
#define NV84_EVO_CRTC_CURSOR_DMA 0x0000089c
#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE 0xffffffff
#define NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE 0x00000000
#define NV50_EVO_CRTC_DITHER_CTRL 0x000008a0
#define NV50_EVO_CRTC_DITHER_CTRL_OFF 0x00000000
#define NV50_EVO_CRTC_DITHER_CTRL_ON 0x00000011
#define NV50_EVO_CRTC_SCALE_CTRL 0x000008a4
#define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000
#define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009
#define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8
#define NV50_EVO_CRTC_COLOR_CTRL_VIBRANCE 0x000fff00
#define NV50_EVO_CRTC_COLOR_CTRL_HUE 0xfff00000
#define NV50_EVO_CRTC_FB_POS 0x000008c0
#define NV50_EVO_CRTC_REAL_RES 0x000008c8
#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4
#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) \
((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF))
/* Both of these are needed, otherwise nothing happens. */
#define NV50_EVO_CRTC_SCALE_RES1 0x000008d8
#define NV50_EVO_CRTC_SCALE_RES2 0x000008dc
#define NV50_EVO_CRTC_UNK900 0x00000900
#define NV50_EVO_CRTC_UNK904 0x00000904
#endif
drivers/gpu/drm/nouveau/nv50_fence.c
浏览文件 @
4f6029da
...
...
@@ -70,7 +70,7 @@ nv50_fence_context_new(struct nouveau_channel *chan)
/* dma objects for display sync channel semaphore blocks */
for
(
i
=
0
;
!
ret
&&
i
<
dev
->
mode_config
.
num_crtc
;
i
++
)
{
struct
nouveau_bo
*
bo
=
nv
5
0_display_crtc_sema
(
dev
,
i
);
struct
nouveau_bo
*
bo
=
nv
d
0_display_crtc_sema
(
dev
,
i
);
ret
=
nouveau_object_new
(
nv_object
(
chan
->
cli
),
chan
->
handle
,
NvEvoSema0
+
i
,
0x003d
,
...
...
drivers/gpu/drm/nouveau/nv50_pm.c
浏览文件 @
4f6029da
...
...
@@ -546,7 +546,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl,
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_device
*
device
=
nouveau_dev
(
dev
);
u32
crtc_mask
=
nv50_display_active_crtcs
(
dev
);
u32
crtc_mask
=
0
;
/*XXX: nv50_display_active_crtcs(dev); */
struct
nouveau_mem_exec_func
exec
=
{
.
dev
=
dev
,
.
precharge
=
mclk_precharge
,
...
...
drivers/gpu/drm/nouveau/nv50_sor.c
已删除
100644 → 0
浏览文件 @
f9887d09
/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
#include "nouveau_reg.h"
#include "nouveau_drm.h"
#include "nouveau_dma.h"
#include "nouveau_encoder.h"
#include "nouveau_connector.h"
#include "nouveau_crtc.h"
#include "nv50_display.h"
#include <core/class.h>
#include <subdev/timer.h>
static
void
nv50_sor_disconnect
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
nouveau_channel
*
evo
=
nv50_display
(
dev
)
->
master
;
int
ret
;
if
(
!
nv_encoder
->
crtc
)
return
;
nv50_crtc_blank
(
nouveau_crtc
(
nv_encoder
->
crtc
),
true
);
NV_DEBUG
(
drm
,
"Disconnecting SOR %d
\n
"
,
nv_encoder
->
or
);
ret
=
RING_SPACE
(
evo
,
4
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while disconnecting SOR
\n
"
);
return
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_SOR
(
nv_encoder
->
or
,
MODE_CTRL
),
1
);
OUT_RING
(
evo
,
0
);
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_UPDATE
,
1
);
OUT_RING
(
evo
,
0
);
nouveau_hdmi_mode_set
(
encoder
,
NULL
);
nv_encoder
->
crtc
=
NULL
;
nv_encoder
->
last_dpms
=
DRM_MODE_DPMS_OFF
;
}
static
void
nv50_sor_dpms
(
struct
drm_encoder
*
encoder
,
int
mode
)
{
struct
nv50_display
*
priv
=
nv50_display
(
encoder
->
dev
);
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
drm_device
*
dev
=
encoder
->
dev
;
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
drm_encoder
*
enc
;
int
or
=
nv_encoder
->
or
;
NV_DEBUG
(
drm
,
"or %d type %d mode %d
\n
"
,
or
,
nv_encoder
->
dcb
->
type
,
mode
);
nv_encoder
->
last_dpms
=
mode
;
list_for_each_entry
(
enc
,
&
dev
->
mode_config
.
encoder_list
,
head
)
{
struct
nouveau_encoder
*
nvenc
=
nouveau_encoder
(
enc
);
if
(
nvenc
==
nv_encoder
||
(
nvenc
->
dcb
->
type
!=
DCB_OUTPUT_TMDS
&&
nvenc
->
dcb
->
type
!=
DCB_OUTPUT_LVDS
&&
nvenc
->
dcb
->
type
!=
DCB_OUTPUT_DP
)
||
nvenc
->
dcb
->
or
!=
nv_encoder
->
dcb
->
or
)
continue
;
if
(
nvenc
->
last_dpms
==
DRM_MODE_DPMS_ON
)
return
;
}
nv_call
(
priv
->
core
,
NV50_DISP_SOR_PWR
+
or
,
(
mode
==
DRM_MODE_DPMS_ON
));
if
(
nv_encoder
->
dcb
->
type
==
DCB_OUTPUT_DP
)
nouveau_dp_dpms
(
encoder
,
mode
,
nv_encoder
->
dp
.
datarate
,
priv
->
core
);
}
static
void
nv50_sor_save
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
NV_ERROR
(
drm
,
"!!
\n
"
);
}
static
void
nv50_sor_restore
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
NV_ERROR
(
drm
,
"!!
\n
"
);
}
static
bool
nv50_sor_mode_fixup
(
struct
drm_encoder
*
encoder
,
const
struct
drm_display_mode
*
mode
,
struct
drm_display_mode
*
adjusted_mode
)
{
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_connector
*
connector
;
NV_DEBUG
(
drm
,
"or %d
\n
"
,
nv_encoder
->
or
);
connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
!
connector
)
{
NV_ERROR
(
drm
,
"Encoder has no connector
\n
"
);
return
false
;
}
if
(
connector
->
scaling_mode
!=
DRM_MODE_SCALE_NONE
&&
connector
->
native_mode
)
drm_mode_copy
(
adjusted_mode
,
connector
->
native_mode
);
return
true
;
}
static
void
nv50_sor_prepare
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
nv50_sor_disconnect
(
encoder
);
if
(
nv_encoder
->
dcb
->
type
==
DCB_OUTPUT_DP
)
{
/* avoid race between link training and supervisor intr */
nv50_display_sync
(
encoder
->
dev
);
}
}
static
void
nv50_sor_commit
(
struct
drm_encoder
*
encoder
)
{
}
static
void
nv50_sor_mode_set
(
struct
drm_encoder
*
encoder
,
struct
drm_display_mode
*
umode
,
struct
drm_display_mode
*
mode
)
{
struct
nouveau_channel
*
evo
=
nv50_display
(
encoder
->
dev
)
->
master
;
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
struct
nouveau_drm
*
drm
=
nouveau_drm
(
encoder
->
dev
);
struct
nouveau_crtc
*
crtc
=
nouveau_crtc
(
encoder
->
crtc
);
struct
nouveau_connector
*
nv_connector
;
struct
nv50_display
*
disp
=
nv50_display
(
encoder
->
dev
);
struct
nvbios
*
bios
=
&
drm
->
vbios
;
uint32_t
mode_ctl
=
0
,
script
;
int
ret
;
NV_DEBUG
(
drm
,
"or %d type %d -> crtc %d
\n
"
,
nv_encoder
->
or
,
nv_encoder
->
dcb
->
type
,
crtc
->
index
);
nv_encoder
->
crtc
=
encoder
->
crtc
;
switch
(
nv_encoder
->
dcb
->
type
)
{
case
DCB_OUTPUT_TMDS
:
if
(
nv_encoder
->
dcb
->
sorconf
.
link
&
1
)
{
if
(
mode
->
clock
<
165000
)
mode_ctl
=
0x0100
;
else
mode_ctl
=
0x0500
;
}
else
mode_ctl
=
0x0200
;
nouveau_hdmi_mode_set
(
encoder
,
mode
);
break
;
case
DCB_OUTPUT_LVDS
:
script
=
0x0000
;
if
(
bios
->
fp_no_ddc
)
{
if
(
bios
->
fp
.
dual_link
)
script
|=
0x0100
;
if
(
bios
->
fp
.
if_is_24bit
)
script
|=
0x0200
;
}
else
{
/* determine number of lvds links */
nv_connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
nv_connector
&&
nv_connector
->
edid
&&
nv_connector
->
type
==
DCB_CONNECTOR_LVDS_SPWG
)
{
/* http://www.spwg.org */
if
(((
u8
*
)
nv_connector
->
edid
)[
121
]
==
2
)
script
|=
0x0100
;
}
else
if
(
mode
->
clock
>=
bios
->
fp
.
duallink_transition_clk
)
{
script
|=
0x0100
;
}
/* determine panel depth */
if
(
script
&
0x0100
)
{
if
(
bios
->
fp
.
strapless_is_24bit
&
2
)
script
|=
0x0200
;
}
else
{
if
(
bios
->
fp
.
strapless_is_24bit
&
1
)
script
|=
0x0200
;
}
if
(
nv_connector
&&
nv_connector
->
edid
&&
(
nv_connector
->
edid
->
revision
>=
4
)
&&
(
nv_connector
->
edid
->
input
&
0x70
)
>=
0x20
)
script
|=
0x0200
;
}
nv_call
(
disp
->
core
,
NV50_DISP_SOR_LVDS_SCRIPT
+
nv_encoder
->
or
,
script
);
break
;
case
DCB_OUTPUT_DP
:
nv_connector
=
nouveau_encoder_connector_get
(
nv_encoder
);
if
(
nv_connector
&&
nv_connector
->
base
.
display_info
.
bpc
==
6
)
{
nv_encoder
->
dp
.
datarate
=
mode
->
clock
*
18
/
8
;
mode_ctl
|=
0x00020000
;
}
else
{
nv_encoder
->
dp
.
datarate
=
mode
->
clock
*
24
/
8
;
mode_ctl
|=
0x00050000
;
}
if
(
nv_encoder
->
dcb
->
sorconf
.
link
&
1
)
mode_ctl
|=
0x00000800
;
else
mode_ctl
|=
0x00000900
;
break
;
default:
break
;
}
if
(
crtc
->
index
==
1
)
mode_ctl
|=
NV50_EVO_SOR_MODE_CTRL_CRTC1
;
else
mode_ctl
|=
NV50_EVO_SOR_MODE_CTRL_CRTC0
;
if
(
mode
->
flags
&
DRM_MODE_FLAG_NHSYNC
)
mode_ctl
|=
NV50_EVO_SOR_MODE_CTRL_NHSYNC
;
if
(
mode
->
flags
&
DRM_MODE_FLAG_NVSYNC
)
mode_ctl
|=
NV50_EVO_SOR_MODE_CTRL_NVSYNC
;
nv50_sor_dpms
(
encoder
,
DRM_MODE_DPMS_ON
);
ret
=
RING_SPACE
(
evo
,
2
);
if
(
ret
)
{
NV_ERROR
(
drm
,
"no space while connecting SOR
\n
"
);
nv_encoder
->
crtc
=
NULL
;
return
;
}
BEGIN_NV04
(
evo
,
0
,
NV50_EVO_SOR
(
nv_encoder
->
or
,
MODE_CTRL
),
1
);
OUT_RING
(
evo
,
mode_ctl
);
}
static
struct
drm_crtc
*
nv50_sor_crtc_get
(
struct
drm_encoder
*
encoder
)
{
return
nouveau_encoder
(
encoder
)
->
crtc
;
}
static
const
struct
drm_encoder_helper_funcs
nv50_sor_helper_funcs
=
{
.
dpms
=
nv50_sor_dpms
,
.
save
=
nv50_sor_save
,
.
restore
=
nv50_sor_restore
,
.
mode_fixup
=
nv50_sor_mode_fixup
,
.
prepare
=
nv50_sor_prepare
,
.
commit
=
nv50_sor_commit
,
.
mode_set
=
nv50_sor_mode_set
,
.
get_crtc
=
nv50_sor_crtc_get
,
.
detect
=
NULL
,
.
disable
=
nv50_sor_disconnect
};
static
void
nv50_sor_destroy
(
struct
drm_encoder
*
encoder
)
{
struct
nouveau_encoder
*
nv_encoder
=
nouveau_encoder
(
encoder
);
drm_encoder_cleanup
(
encoder
);
kfree
(
nv_encoder
);
}
static
const
struct
drm_encoder_funcs
nv50_sor_encoder_funcs
=
{
.
destroy
=
nv50_sor_destroy
,
};
int
nv50_sor_create
(
struct
drm_connector
*
connector
,
struct
dcb_output
*
entry
)
{
struct
nouveau_encoder
*
nv_encoder
=
NULL
;
struct
drm_device
*
dev
=
connector
->
dev
;
struct
drm_encoder
*
encoder
;
int
type
;
switch
(
entry
->
type
)
{
case
DCB_OUTPUT_TMDS
:
case
DCB_OUTPUT_DP
:
type
=
DRM_MODE_ENCODER_TMDS
;
break
;
case
DCB_OUTPUT_LVDS
:
type
=
DRM_MODE_ENCODER_LVDS
;
break
;
default:
return
-
EINVAL
;
}
nv_encoder
=
kzalloc
(
sizeof
(
*
nv_encoder
),
GFP_KERNEL
);
if
(
!
nv_encoder
)
return
-
ENOMEM
;
encoder
=
to_drm_encoder
(
nv_encoder
);
nv_encoder
->
dcb
=
entry
;
nv_encoder
->
or
=
ffs
(
entry
->
or
)
-
1
;
nv_encoder
->
last_dpms
=
DRM_MODE_DPMS_OFF
;
drm_encoder_init
(
dev
,
encoder
,
&
nv50_sor_encoder_funcs
,
type
);
drm_encoder_helper_add
(
encoder
,
&
nv50_sor_helper_funcs
);
encoder
->
possible_crtcs
=
entry
->
heads
;
encoder
->
possible_clones
=
0
;
drm_mode_connector_attach_encoder
(
connector
,
encoder
);
return
0
;
}
drivers/gpu/drm/nouveau/nv84_fence.c
浏览文件 @
4f6029da
...
...
@@ -127,7 +127,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
/* dma objects for display sync channel semaphore blocks */
for
(
i
=
0
;
!
ret
&&
i
<
dev
->
mode_config
.
num_crtc
;
i
++
)
{
struct
nouveau_bo
*
bo
=
nv
5
0_display_crtc_sema
(
dev
,
i
);
struct
nouveau_bo
*
bo
=
nv
d
0_display_crtc_sema
(
dev
,
i
);
ret
=
nouveau_object_new
(
nv_object
(
chan
->
cli
),
chan
->
handle
,
NvEvoSema0
+
i
,
0x003d
,
...
...
drivers/gpu/drm/nouveau/nvc0_fence.c
浏览文件 @
4f6029da
...
...
@@ -114,17 +114,9 @@ nvc0_fence_context_del(struct nouveau_channel *chan)
struct
nvc0_fence_chan
*
fctx
=
chan
->
fence
;
int
i
;
if
(
nv_device
(
chan
->
drm
->
device
)
->
card_type
>=
NV_D0
)
{
for
(
i
=
0
;
i
<
dev
->
mode_config
.
num_crtc
;
i
++
)
{
struct
nouveau_bo
*
bo
=
nvd0_display_crtc_sema
(
dev
,
i
);
nouveau_bo_vma_del
(
bo
,
&
fctx
->
dispc_vma
[
i
]);
}
}
else
if
(
nv_device
(
chan
->
drm
->
device
)
->
card_type
>=
NV_50
)
{
for
(
i
=
0
;
i
<
dev
->
mode_config
.
num_crtc
;
i
++
)
{
struct
nouveau_bo
*
bo
=
nv50_display_crtc_sema
(
dev
,
i
);
nouveau_bo_vma_del
(
bo
,
&
fctx
->
dispc_vma
[
i
]);
}
for
(
i
=
0
;
i
<
dev
->
mode_config
.
num_crtc
;
i
++
)
{
struct
nouveau_bo
*
bo
=
nvd0_display_crtc_sema
(
dev
,
i
);
nouveau_bo_vma_del
(
bo
,
&
fctx
->
dispc_vma
[
i
]);
}
nouveau_bo_vma_del
(
priv
->
bo
,
&
fctx
->
vma
);
...
...
@@ -154,12 +146,7 @@ nvc0_fence_context_new(struct nouveau_channel *chan)
/* map display semaphore buffers into channel's vm */
for
(
i
=
0
;
!
ret
&&
i
<
chan
->
drm
->
dev
->
mode_config
.
num_crtc
;
i
++
)
{
struct
nouveau_bo
*
bo
;
if
(
nv_device
(
chan
->
drm
->
device
)
->
card_type
>=
NV_D0
)
bo
=
nvd0_display_crtc_sema
(
chan
->
drm
->
dev
,
i
);
else
bo
=
nv50_display_crtc_sema
(
chan
->
drm
->
dev
,
i
);
struct
nouveau_bo
*
bo
=
nvd0_display_crtc_sema
(
chan
->
drm
->
dev
,
i
);
ret
=
nouveau_bo_vma_add
(
bo
,
client
->
vm
,
&
fctx
->
dispc_vma
[
i
]);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录