Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
4f47643d
Commit
4f47643d
authored
Feb 03, 2013
by
Ben Skeggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/nouveau/gpio: use event interfaces for interrupt signalling
Signed-off-by:
Ben Skeggs
<
bskeggs@redhat.com
>
parent
0f080066
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
127 additions
and
219 deletions
+127
-219
drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
+13
-18
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
+9
-128
drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
+22
-11
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
+27
-12
drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
+3
-1
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.c
+35
-42
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/nouveau/nouveau_connector.h
+6
-1
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.c
+8
-4
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_dp.c
+4
-2
No files found.
drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
View file @
4f47643d
...
...
@@ -3,6 +3,7 @@
#include <core/subdev.h>
#include <core/device.h>
#include <core/event.h>
#include <subdev/bios.h>
#include <subdev/bios/gpio.h>
...
...
@@ -10,28 +11,18 @@
struct
nouveau_gpio
{
struct
nouveau_subdev
base
;
struct
nouveau_event
*
events
;
/* hardware interfaces */
void
(
*
reset
)(
struct
nouveau_gpio
*
,
u8
func
);
int
(
*
drive
)(
struct
nouveau_gpio
*
,
int
line
,
int
dir
,
int
out
);
int
(
*
sense
)(
struct
nouveau_gpio
*
,
int
line
);
void
(
*
irq_enable
)(
struct
nouveau_gpio
*
,
int
line
,
bool
);
/* software interfaces */
int
(
*
find
)(
struct
nouveau_gpio
*
,
int
idx
,
u8
tag
,
u8
line
,
struct
dcb_gpio_func
*
);
int
(
*
set
)(
struct
nouveau_gpio
*
,
int
idx
,
u8
tag
,
u8
line
,
int
state
);
int
(
*
get
)(
struct
nouveau_gpio
*
,
int
idx
,
u8
tag
,
u8
line
);
int
(
*
irq
)(
struct
nouveau_gpio
*
,
int
idx
,
u8
tag
,
u8
line
,
bool
on
);
/* interrupt handling */
struct
list_head
isr
;
spinlock_t
lock
;
void
(
*
isr_run
)(
struct
nouveau_gpio
*
,
int
idx
,
u32
mask
);
int
(
*
isr_add
)(
struct
nouveau_gpio
*
,
int
idx
,
u8
tag
,
u8
line
,
void
(
*
)(
void
*
,
int
state
),
void
*
data
);
void
(
*
isr_del
)(
struct
nouveau_gpio
*
,
int
idx
,
u8
tag
,
u8
line
,
void
(
*
)(
void
*
,
int
state
),
void
*
data
);
};
static
inline
struct
nouveau_gpio
*
...
...
@@ -42,14 +33,17 @@ nouveau_gpio(void *obj)
#define nouveau_gpio_create(p,e,o,l,d) \
nouveau_gpio_create_((p), (e), (o), (l), sizeof(**d), (void **)d)
#define nouveau_gpio_destroy(p) \
nouveau_subdev_destroy(&(p)->base)
#define nouveau_gpio_destroy(p) ({ \
struct nouveau_gpio *gpio = (p); \
_nouveau_gpio_dtor(nv_object(gpio)); \
})
#define nouveau_gpio_fini(p,s) \
nouveau_subdev_fini(&(p)->base, (s))
int
nouveau_gpio_create_
(
struct
nouveau_object
*
,
struct
nouveau_object
*
,
struct
nouveau_oclass
*
,
int
,
int
,
void
**
);
int
nouveau_gpio_init
(
struct
nouveau_gpio
*
);
int
nouveau_gpio_create_
(
struct
nouveau_object
*
,
struct
nouveau_object
*
,
struct
nouveau_oclass
*
,
int
,
int
,
void
**
);
void
_nouveau_gpio_dtor
(
struct
nouveau_object
*
);
int
nouveau_gpio_init
(
struct
nouveau_gpio
*
);
extern
struct
nouveau_oclass
nv10_gpio_oclass
;
extern
struct
nouveau_oclass
nv50_gpio_oclass
;
...
...
@@ -59,6 +53,7 @@ void nv50_gpio_dtor(struct nouveau_object *);
int
nv50_gpio_init
(
struct
nouveau_object
*
);
int
nv50_gpio_fini
(
struct
nouveau_object
*
,
bool
);
void
nv50_gpio_intr
(
struct
nouveau_subdev
*
);
void
nv50_gpio_irq_enable
(
struct
nouveau_gpio
*
,
int
line
,
bool
);
void
nv50_gpio_intr_enable
(
struct
nouveau_event
*
,
int
line
);
void
nv50_gpio_intr_disable
(
struct
nouveau_event
*
,
int
line
);
#endif
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
View file @
4f47643d
...
...
@@ -102,129 +102,12 @@ nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line)
return
ret
;
}
static
int
nouveau_gpio_irq
(
struct
nouveau_gpio
*
gpio
,
int
idx
,
u8
tag
,
u8
line
,
bool
on
)
{
struct
dcb_gpio_func
func
;
int
ret
;
ret
=
nouveau_gpio_find
(
gpio
,
idx
,
tag
,
line
,
&
func
);
if
(
ret
==
0
)
{
if
(
idx
==
0
&&
gpio
->
irq_enable
)
gpio
->
irq_enable
(
gpio
,
func
.
line
,
on
);
else
ret
=
-
ENODEV
;
}
return
ret
;
}
struct
gpio_isr
{
struct
nouveau_gpio
*
gpio
;
struct
list_head
head
;
struct
work_struct
work
;
int
idx
;
struct
dcb_gpio_func
func
;
void
(
*
handler
)(
void
*
,
int
);
void
*
data
;
bool
inhibit
;
};
static
void
nouveau_gpio_isr_bh
(
struct
work_struct
*
work
)
{
struct
gpio_isr
*
isr
=
container_of
(
work
,
struct
gpio_isr
,
work
);
struct
nouveau_gpio
*
gpio
=
isr
->
gpio
;
unsigned
long
flags
;
int
state
;
state
=
nouveau_gpio_get
(
gpio
,
isr
->
idx
,
isr
->
func
.
func
,
isr
->
func
.
line
);
if
(
state
>=
0
)
isr
->
handler
(
isr
->
data
,
state
);
spin_lock_irqsave
(
&
gpio
->
lock
,
flags
);
isr
->
inhibit
=
false
;
spin_unlock_irqrestore
(
&
gpio
->
lock
,
flags
);
}
static
void
nouveau_gpio_isr_run
(
struct
nouveau_gpio
*
gpio
,
int
idx
,
u32
line_mask
)
{
struct
gpio_isr
*
isr
;
if
(
idx
!=
0
)
return
;
spin_lock
(
&
gpio
->
lock
);
list_for_each_entry
(
isr
,
&
gpio
->
isr
,
head
)
{
if
(
line_mask
&
(
1
<<
isr
->
func
.
line
))
{
if
(
isr
->
inhibit
)
continue
;
isr
->
inhibit
=
true
;
schedule_work
(
&
isr
->
work
);
}
}
spin_unlock
(
&
gpio
->
lock
);
}
static
int
nouveau_gpio_isr_add
(
struct
nouveau_gpio
*
gpio
,
int
idx
,
u8
tag
,
u8
line
,
void
(
*
handler
)(
void
*
,
int
),
void
*
data
)
{
struct
gpio_isr
*
isr
;
unsigned
long
flags
;
int
ret
;
isr
=
kzalloc
(
sizeof
(
*
isr
),
GFP_KERNEL
);
if
(
!
isr
)
return
-
ENOMEM
;
ret
=
nouveau_gpio_find
(
gpio
,
idx
,
tag
,
line
,
&
isr
->
func
);
if
(
ret
)
{
kfree
(
isr
);
return
ret
;
}
INIT_WORK
(
&
isr
->
work
,
nouveau_gpio_isr_bh
);
isr
->
gpio
=
gpio
;
isr
->
handler
=
handler
;
isr
->
data
=
data
;
isr
->
idx
=
idx
;
spin_lock_irqsave
(
&
gpio
->
lock
,
flags
);
list_add
(
&
isr
->
head
,
&
gpio
->
isr
);
spin_unlock_irqrestore
(
&
gpio
->
lock
,
flags
);
return
0
;
}
static
void
nouveau_gpio_isr_del
(
struct
nouveau_gpio
*
gpio
,
int
idx
,
u8
tag
,
u8
line
,
void
(
*
handler
)(
void
*
,
int
),
void
*
data
)
void
_nouveau_gpio_dtor
(
struct
nouveau_object
*
object
)
{
struct
gpio_isr
*
isr
,
*
tmp
;
struct
dcb_gpio_func
func
;
unsigned
long
flags
;
LIST_HEAD
(
tofree
);
int
ret
;
ret
=
nouveau_gpio_find
(
gpio
,
idx
,
tag
,
line
,
&
func
);
if
(
ret
==
0
)
{
spin_lock_irqsave
(
&
gpio
->
lock
,
flags
);
list_for_each_entry_safe
(
isr
,
tmp
,
&
gpio
->
isr
,
head
)
{
if
(
memcmp
(
&
isr
->
func
,
&
func
,
sizeof
(
func
))
||
isr
->
idx
!=
idx
||
isr
->
handler
!=
handler
||
isr
->
data
!=
data
)
continue
;
list_move_tail
(
&
isr
->
head
,
&
tofree
);
}
spin_unlock_irqrestore
(
&
gpio
->
lock
,
flags
);
list_for_each_entry_safe
(
isr
,
tmp
,
&
tofree
,
head
)
{
flush_work
(
&
isr
->
work
);
kfree
(
isr
);
}
}
struct
nouveau_gpio
*
gpio
=
(
void
*
)
object
;
nouveau_event_destroy
(
&
gpio
->
events
);
nouveau_subdev_destroy
(
&
gpio
->
base
);
}
int
...
...
@@ -242,15 +125,13 @@ nouveau_gpio_create_(struct nouveau_object *parent,
if
(
ret
)
return
ret
;
ret
=
nouveau_event_create
(
lines
,
&
gpio
->
events
);
if
(
ret
)
return
ret
;
gpio
->
find
=
nouveau_gpio_find
;
gpio
->
set
=
nouveau_gpio_set
;
gpio
->
get
=
nouveau_gpio_get
;
gpio
->
irq
=
nouveau_gpio_irq
;
gpio
->
isr_run
=
nouveau_gpio_isr_run
;
gpio
->
isr_add
=
nouveau_gpio_isr_add
;
gpio
->
isr_del
=
nouveau_gpio_isr_del
;
INIT_LIST_HEAD
(
&
gpio
->
isr
);
spin_lock_init
(
&
gpio
->
lock
);
return
0
;
}
...
...
drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
View file @
4f47643d
...
...
@@ -82,15 +82,6 @@ nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out)
return
0
;
}
static
void
nv10_gpio_irq_enable
(
struct
nouveau_gpio
*
gpio
,
int
line
,
bool
on
)
{
u32
mask
=
0x00010001
<<
line
;
nv_wr32
(
gpio
,
0x001104
,
mask
);
nv_mask
(
gpio
,
0x001144
,
mask
,
on
?
mask
:
0
);
}
static
void
nv10_gpio_intr
(
struct
nouveau_subdev
*
subdev
)
{
...
...
@@ -98,12 +89,30 @@ nv10_gpio_intr(struct nouveau_subdev *subdev)
u32
intr
=
nv_rd32
(
priv
,
0x001104
);
u32
hi
=
(
intr
&
0x0000ffff
)
>>
0
;
u32
lo
=
(
intr
&
0xffff0000
)
>>
16
;
int
i
;
priv
->
base
.
isr_run
(
&
priv
->
base
,
0
,
hi
|
lo
);
for
(
i
=
0
;
(
hi
|
lo
)
&&
i
<
32
;
i
++
)
{
if
((
hi
|
lo
)
&
(
1
<<
i
))
nouveau_event_trigger
(
priv
->
base
.
events
,
i
);
}
nv_wr32
(
priv
,
0x001104
,
intr
);
}
static
void
nv10_gpio_intr_enable
(
struct
nouveau_event
*
event
,
int
line
)
{
nv_wr32
(
event
->
priv
,
0x001104
,
0x00010001
<<
line
);
nv_mask
(
event
->
priv
,
0x001144
,
0x00010001
<<
line
,
0x00010001
<<
line
);
}
static
void
nv10_gpio_intr_disable
(
struct
nouveau_event
*
event
,
int
line
)
{
nv_wr32
(
event
->
priv
,
0x001104
,
0x00010001
<<
line
);
nv_mask
(
event
->
priv
,
0x001144
,
0x00010001
<<
line
,
0x00000000
);
}
static
int
nv10_gpio_ctor
(
struct
nouveau_object
*
parent
,
struct
nouveau_object
*
engine
,
struct
nouveau_oclass
*
oclass
,
void
*
data
,
u32
size
,
...
...
@@ -119,7 +128,9 @@ nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv
->
base
.
drive
=
nv10_gpio_drive
;
priv
->
base
.
sense
=
nv10_gpio_sense
;
priv
->
base
.
irq_enable
=
nv10_gpio_irq_enable
;
priv
->
base
.
events
->
priv
=
priv
;
priv
->
base
.
events
->
enable
=
nv10_gpio_intr_enable
;
priv
->
base
.
events
->
disable
=
nv10_gpio_intr_disable
;
nv_subdev
(
priv
)
->
intr
=
nv10_gpio_intr
;
return
0
;
}
...
...
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
View file @
4f47643d
...
...
@@ -94,22 +94,13 @@ nv50_gpio_sense(struct nouveau_gpio *gpio, int line)
return
!!
(
nv_rd32
(
gpio
,
reg
)
&
(
4
<<
shift
));
}
void
nv50_gpio_irq_enable
(
struct
nouveau_gpio
*
gpio
,
int
line
,
bool
on
)
{
u32
reg
=
line
<
16
?
0xe050
:
0xe070
;
u32
mask
=
0x00010001
<<
(
line
&
0xf
);
nv_wr32
(
gpio
,
reg
+
4
,
mask
);
nv_mask
(
gpio
,
reg
+
0
,
mask
,
on
?
mask
:
0
);
}
void
nv50_gpio_intr
(
struct
nouveau_subdev
*
subdev
)
{
struct
nv50_gpio_priv
*
priv
=
(
void
*
)
subdev
;
u32
intr0
,
intr1
=
0
;
u32
hi
,
lo
;
int
i
;
intr0
=
nv_rd32
(
priv
,
0xe054
)
&
nv_rd32
(
priv
,
0xe050
);
if
(
nv_device
(
priv
)
->
chipset
>=
0x90
)
...
...
@@ -117,13 +108,35 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
hi
=
(
intr0
&
0x0000ffff
)
|
(
intr1
<<
16
);
lo
=
(
intr0
>>
16
)
|
(
intr1
&
0xffff0000
);
priv
->
base
.
isr_run
(
&
priv
->
base
,
0
,
hi
|
lo
);
for
(
i
=
0
;
(
hi
|
lo
)
&&
i
<
32
;
i
++
)
{
if
((
hi
|
lo
)
&
(
1
<<
i
))
nouveau_event_trigger
(
priv
->
base
.
events
,
i
);
}
nv_wr32
(
priv
,
0xe054
,
intr0
);
if
(
nv_device
(
priv
)
->
chipset
>=
0x90
)
nv_wr32
(
priv
,
0xe074
,
intr1
);
}
void
nv50_gpio_intr_enable
(
struct
nouveau_event
*
event
,
int
line
)
{
const
u32
addr
=
line
<
16
?
0xe050
:
0xe070
;
const
u32
mask
=
0x00010001
<<
(
line
&
0xf
);
nv_wr32
(
event
->
priv
,
addr
+
0x04
,
mask
);
nv_mask
(
event
->
priv
,
addr
+
0x00
,
mask
,
mask
);
}
void
nv50_gpio_intr_disable
(
struct
nouveau_event
*
event
,
int
line
)
{
const
u32
addr
=
line
<
16
?
0xe050
:
0xe070
;
const
u32
mask
=
0x00010001
<<
(
line
&
0xf
);
nv_wr32
(
event
->
priv
,
addr
+
0x04
,
mask
);
nv_mask
(
event
->
priv
,
addr
+
0x00
,
mask
,
0x00000000
);
}
static
int
nv50_gpio_ctor
(
struct
nouveau_object
*
parent
,
struct
nouveau_object
*
engine
,
struct
nouveau_oclass
*
oclass
,
void
*
data
,
u32
size
,
...
...
@@ -142,7 +155,9 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv
->
base
.
reset
=
nv50_gpio_reset
;
priv
->
base
.
drive
=
nv50_gpio_drive
;
priv
->
base
.
sense
=
nv50_gpio_sense
;
priv
->
base
.
irq_enable
=
nv50_gpio_irq_enable
;
priv
->
base
.
events
->
priv
=
priv
;
priv
->
base
.
events
->
enable
=
nv50_gpio_intr_enable
;
priv
->
base
.
events
->
disable
=
nv50_gpio_intr_disable
;
nv_subdev
(
priv
)
->
intr
=
nv50_gpio_intr
;
return
0
;
}
...
...
drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
View file @
4f47643d
...
...
@@ -88,7 +88,9 @@ nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
priv
->
base
.
reset
=
nvd0_gpio_reset
;
priv
->
base
.
drive
=
nvd0_gpio_drive
;
priv
->
base
.
sense
=
nvd0_gpio_sense
;
priv
->
base
.
irq_enable
=
nv50_gpio_irq_enable
;
priv
->
base
.
events
->
priv
=
priv
;
priv
->
base
.
events
->
enable
=
nv50_gpio_intr_enable
;
priv
->
base
.
events
->
disable
=
nv50_gpio_intr_disable
;
nv_subdev
(
priv
)
->
intr
=
nv50_gpio_intr
;
return
0
;
}
...
...
drivers/gpu/drm/nouveau/nouveau_connector.c
View file @
4f47643d
...
...
@@ -55,8 +55,6 @@ MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)");
static
int
nouveau_duallink
=
1
;
module_param_named
(
duallink
,
nouveau_duallink
,
int
,
0400
);
static
void
nouveau_connector_hotplug
(
void
*
,
int
);
struct
nouveau_encoder
*
find_encoder
(
struct
drm_connector
*
connector
,
int
type
)
{
...
...
@@ -100,22 +98,6 @@ static void
nouveau_connector_destroy
(
struct
drm_connector
*
connector
)
{
struct
nouveau_connector
*
nv_connector
=
nouveau_connector
(
connector
);
struct
nouveau_gpio
*
gpio
;
struct
nouveau_drm
*
drm
;
struct
drm_device
*
dev
;
if
(
!
nv_connector
)
return
;
dev
=
nv_connector
->
base
.
dev
;
drm
=
nouveau_drm
(
dev
);
gpio
=
nouveau_gpio
(
drm
->
device
);
if
(
gpio
&&
nv_connector
->
hpd
.
func
!=
DCB_GPIO_UNUSED
)
{
gpio
->
isr_del
(
gpio
,
0
,
nv_connector
->
hpd
.
func
,
0xff
,
nouveau_connector_hotplug
,
connector
);
}
kfree
(
nv_connector
->
edid
);
drm_sysfs_connector_remove
(
connector
);
drm_connector_cleanup
(
connector
);
...
...
@@ -912,6 +894,37 @@ nouveau_connector_funcs_lvds = {
.
force
=
nouveau_connector_force
};
static
void
nouveau_connector_hotplug_work
(
struct
work_struct
*
work
)
{
struct
nouveau_connector
*
nv_connector
=
container_of
(
work
,
struct
nouveau_connector
,
hpd_work
);
struct
drm_connector
*
connector
=
&
nv_connector
->
base
;
struct
drm_device
*
dev
=
connector
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
struct
nouveau_gpio
*
gpio
=
nouveau_gpio
(
drm
->
device
);
bool
plugged
=
gpio
->
get
(
gpio
,
0
,
nv_connector
->
hpd
.
func
,
0xff
);
NV_DEBUG
(
drm
,
"%splugged %s
\n
"
,
plugged
?
""
:
"un"
,
drm_get_connector_name
(
connector
));
if
(
plugged
)
drm_helper_connector_dpms
(
connector
,
DRM_MODE_DPMS_ON
);
else
drm_helper_connector_dpms
(
connector
,
DRM_MODE_DPMS_OFF
);
drm_helper_hpd_irq_event
(
dev
);
}
static
int
nouveau_connector_hotplug
(
struct
nouveau_eventh
*
event
,
int
index
)
{
struct
nouveau_connector
*
nv_connector
=
container_of
(
event
,
struct
nouveau_connector
,
hpd_func
);
schedule_work
(
&
nv_connector
->
hpd_work
);
return
NVKM_EVENT_KEEP
;
}
static
int
drm_conntype_from_dcb
(
enum
dcb_connector_type
dcb
)
{
...
...
@@ -962,6 +975,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
return
ERR_PTR
(
-
ENOMEM
);
connector
=
&
nv_connector
->
base
;
INIT_WORK
(
&
nv_connector
->
hpd_work
,
nouveau_connector_hotplug_work
);
nv_connector
->
index
=
index
;
/* attempt to parse vbios connector type and hotplug gpio */
...
...
@@ -978,6 +992,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
ret
=
gpio
->
find
(
gpio
,
0
,
hpd
[
ffs
((
entry
&
0x07033000
)
>>
12
)],
DCB_GPIO_UNUSED
,
&
nv_connector
->
hpd
);
nv_connector
->
hpd_func
.
func
=
nouveau_connector_hotplug
;
if
(
ret
)
nv_connector
->
hpd
.
func
=
DCB_GPIO_UNUSED
;
...
...
@@ -1129,31 +1144,9 @@ nouveau_connector_create(struct drm_device *dev, int index)
}
connector
->
polled
=
DRM_CONNECTOR_POLL_CONNECT
;
if
(
gpio
&&
nv_connector
->
hpd
.
func
!=
DCB_GPIO_UNUSED
)
{
ret
=
gpio
->
isr_add
(
gpio
,
0
,
nv_connector
->
hpd
.
func
,
0xff
,
nouveau_connector_hotplug
,
connector
);
if
(
ret
==
0
)
connector
->
polled
=
DRM_CONNECTOR_POLL_HPD
;
}
if
(
nv_connector
->
hpd
.
func
!=
DCB_GPIO_UNUSED
)
connector
->
polled
=
DRM_CONNECTOR_POLL_HPD
;
drm_sysfs_connector_add
(
connector
);
return
connector
;
}
static
void
nouveau_connector_hotplug
(
void
*
data
,
int
plugged
)
{
struct
drm_connector
*
connector
=
data
;
struct
drm_device
*
dev
=
connector
->
dev
;
struct
nouveau_drm
*
drm
=
nouveau_drm
(
dev
);
NV_DEBUG
(
drm
,
"%splugged %s
\n
"
,
plugged
?
""
:
"un"
,
drm_get_connector_name
(
connector
));
if
(
plugged
)
drm_helper_connector_dpms
(
connector
,
DRM_MODE_DPMS_ON
);
else
drm_helper_connector_dpms
(
connector
,
DRM_MODE_DPMS_OFF
);
drm_helper_hpd_irq_event
(
dev
);
}
drivers/gpu/drm/nouveau/nouveau_connector.h
View file @
4f47643d
...
...
@@ -30,6 +30,8 @@
#include <drm/drm_edid.h>
#include "nouveau_crtc.h"
#include <core/event.h>
#include <subdev/bios.h>
#include <subdev/bios/gpio.h>
...
...
@@ -62,10 +64,13 @@ enum nouveau_dithering_depth {
struct
nouveau_connector
{
struct
drm_connector
base
;
enum
dcb_connector_type
type
;
struct
dcb_gpio_func
hpd
;
u8
index
;
u8
*
dcb
;
struct
dcb_gpio_func
hpd
;
struct
work_struct
hpd_work
;
struct
nouveau_eventh
hpd_func
;
int
dithering_mode
;
int
dithering_depth
;
int
scaling_mode
;
...
...
drivers/gpu/drm/nouveau/nouveau_display.c
View file @
4f47643d
...
...
@@ -233,8 +233,10 @@ nouveau_display_init(struct drm_device *dev)
/* enable hotplug interrupts */
list_for_each_entry
(
connector
,
&
dev
->
mode_config
.
connector_list
,
head
)
{
struct
nouveau_connector
*
conn
=
nouveau_connector
(
connector
);
if
(
gpio
)
gpio
->
irq
(
gpio
,
0
,
conn
->
hpd
.
func
,
0xff
,
true
);
if
(
gpio
&&
conn
->
hpd
.
func
!=
DCB_GPIO_UNUSED
)
{
nouveau_event_get
(
gpio
->
events
,
conn
->
hpd
.
line
,
&
conn
->
hpd_func
);
}
}
return
ret
;
...
...
@@ -251,8 +253,10 @@ nouveau_display_fini(struct drm_device *dev)
/* disable hotplug interrupts */
list_for_each_entry
(
connector
,
&
dev
->
mode_config
.
connector_list
,
head
)
{
struct
nouveau_connector
*
conn
=
nouveau_connector
(
connector
);
if
(
gpio
)
gpio
->
irq
(
gpio
,
0
,
conn
->
hpd
.
func
,
0xff
,
false
);
if
(
gpio
&&
conn
->
hpd
.
func
!=
DCB_GPIO_UNUSED
)
{
nouveau_event_put
(
gpio
->
events
,
conn
->
hpd
.
line
,
&
conn
->
hpd_func
);
}
}
drm_kms_helper_poll_disable
(
dev
);
...
...
drivers/gpu/drm/nouveau/nouveau_dp.c
View file @
4f47643d
...
...
@@ -260,7 +260,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
* we take during link training (DP_SET_POWER is one), we need
* to ignore them for the moment to avoid races.
*/
gpio
->
irq
(
gpio
,
0
,
nv_connector
->
hpd
.
func
,
0xff
,
false
);
nouveau_event_put
(
gpio
->
events
,
nv_connector
->
hpd
.
line
,
&
nv_connector
->
hpd_func
);
/* enable down-spreading and execute pre-train script from vbios */
dp_link_train_init
(
dev
,
&
dp
,
nv_encoder
->
dp
.
dpcd
[
3
]
&
1
);
...
...
@@ -300,7 +301,8 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate,
dp_link_train_fini
(
dev
,
&
dp
);
/* re-enable hotplug detect */
gpio
->
irq
(
gpio
,
0
,
nv_connector
->
hpd
.
func
,
0xff
,
true
);
nouveau_event_get
(
gpio
->
events
,
nv_connector
->
hpd
.
line
,
&
nv_connector
->
hpd_func
);
return
true
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment