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
24824a0e
Commit
24824a0e
authored
Apr 07, 2003
by
Alan Cox
Committed by
Linus Torvalds
Apr 07, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] remaining dvb bits
parent
084697f7
Changes
18
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
35716 additions
and
5 deletions
+35716
-5
drivers/media/Kconfig
drivers/media/Kconfig
+19
-0
drivers/media/Makefile
drivers/media/Makefile
+1
-1
drivers/media/dvb/Kconfig
drivers/media/dvb/Kconfig
+3
-3
drivers/media/dvb/Makefile
drivers/media/dvb/Makefile
+1
-1
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/Kconfig
+92
-0
drivers/media/dvb/ttpci/Makefile
drivers/media/dvb/ttpci/Makefile
+18
-0
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.c
+4371
-0
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110.h
+683
-0
drivers/media/dvb/ttpci/av7110_firm.h
drivers/media/dvb/ttpci/av7110_firm.h
+28080
-0
drivers/media/dvb/ttpci/av7110_ipack.c
drivers/media/dvb/ttpci/av7110_ipack.c
+404
-0
drivers/media/dvb/ttpci/av7110_ipack.h
drivers/media/dvb/ttpci/av7110_ipack.h
+13
-0
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/av7110_ir.c
+175
-0
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-av.c
+395
-0
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-ci.c
+434
-0
drivers/media/dvb/ttpci/budget-core.c
drivers/media/dvb/ttpci/budget-core.c
+339
-0
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget-patch.c
+335
-0
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttpci/budget.c
+267
-0
drivers/media/dvb/ttpci/budget.h
drivers/media/dvb/ttpci/budget.h
+86
-0
No files found.
drivers/media/Kconfig
View file @
24824a0e
...
...
@@ -32,5 +32,24 @@ source "drivers/media/radio/Kconfig"
source "drivers/media/dvb/Kconfig"
source "drivers/media/common/Kconfig"
config VIDEO_TUNER
tristate
default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_MXB=y
default m if VIDEO_BT848=m || VIDEO_SAA7134=m || VIDEO_MXB=m
depends on VIDEO_DEV
config VIDEO_BUF
tristate
default y if VIDEO_BT848=y || VIDEO_SAA7134=y || VIDEO_SAA7146=y
default m if VIDEO_BT848=m || VIDEO_SAA7134=m || VIDEO_SAA7146=m
depends on VIDEO_DEV
config VIDEO_BTCX
tristate
default VIDEO_BT848
depends on VIDEO_DEV
endmenu
drivers/media/Makefile
View file @
24824a0e
...
...
@@ -2,4 +2,4 @@
# Makefile for the kernel multimedia device drivers.
#
obj-y
:=
video/ radio/ dvb/
obj-y
:=
video/ radio/ dvb/
common/
drivers/media/dvb/Kconfig
View file @
24824a0e
...
...
@@ -3,7 +3,7 @@
#
menu "Digital Video Broadcasting Devices"
depends on
VIDEO_DEV!=n
depends on
NET && INET
config DVB
bool "DVB For Linux"
...
...
@@ -32,10 +32,10 @@ source "drivers/media/dvb/dvb-core/Kconfig"
source "drivers/media/dvb/frontends/Kconfig"
comment "Supported
DVB
Adapters"
comment "Supported
SAA7146 based PCI
Adapters"
depends on DVB
source "drivers/media/dvb/
av7110
/Kconfig"
source "drivers/media/dvb/
ttpci
/Kconfig"
endmenu
drivers/media/dvb/Makefile
View file @
24824a0e
...
...
@@ -2,4 +2,4 @@
# Makefile for the kernel multimedia device drivers.
#
obj-y
:=
dvb-core/ frontends/
av7110
/
obj-y
:=
dvb-core/ frontends/
ttpci/
# ttusb-budget
/
drivers/media/dvb/ttpci/Kconfig
0 → 100644
View file @
24824a0e
config DVB_AV7110
tristate "AV7110 cards"
depends on VIDEO_DEV && DVB_CORE
help
Support for SAA7146 and AV7110 based DVB cards as produced
by Fujitsu-Siemens, Technotrend, Hauppauge and others.
This driver only supports the fullfeatured cards with
onboard MPEG2 decoder.
Say Y if you own such a card and want to use it.
config DVB_AV7110_OSD
bool "AV7110 OSD support"
depends on DVB_AV7110
help
The AV7110 firmware provides some code to generate an OnScreenDisplay
on the video output. This is kind of nonstandard and not guaranteed to
be maintained.
Anyway, some popular DVB software like VDR uses this OSD to render
its menus, so say Y if you want to use this software.
All other people say N.
config DVB_BUDGET
tristate "Budget cards"
depends on DVB_CORE
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
MPEG2 decoder.
Say Y if you own such a card and want to use it.
This driver is available as a module called
dvb-ttpci-budget.o ( = code which can be inserted in
and removed from the running kernel whenever you want).
If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>.
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
depends on VIDEO_DEV && DVB_CORE && DVB_BUDGET
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
MPEG2 decoder, but with onboard Common Interface connector.
Say Y if you own such a card and want to use it.
This driver is available as a module called
dvb-ttpci-budget-av.o ( = code which can be inserted in
and removed from the running kernel whenever you want).
If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>.
config DVB_BUDGET_AV
tristate "Budget cards with analog video inputs"
depends on VIDEO_DEV && DVB_CORE && DVB_BUDGET
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
MPEG2 decoder, but with one or more analog video inputs.
Say Y if you own such a card and want to use it.
This driver is available as a module called
dvb-ttpci-budget-av.o ( = code which can be inserted in
and removed from the running kernel whenever you want).
here and read <file:Documentation/modules.txt>.
config DVB_BUDGET_PATCH
tristate "AV7110 cards with Budget Patch"
depends on DVB_CORE && DVB_BUDGET
help
Support for Budget Patch (full TS) modification on
SAA7146+AV7110 based cards (DVB-S cards). This
driver doesn't use onboard MPEG2 decoder. The
card is driven in Budget-only mode. Card is
required to have loaded firmware to tune properly.
Firmware can be loaded by insertion and removal of
standard AV7110 driver prior to loading this
driver.
Say Y if you own such a card and want to use it.
This driver is available as a module called
dvb-ttpci-budget-patch.o ( = code which can be inserted in
and removed from the running kernel whenever you want).
If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>.
drivers/media/dvb/ttpci/Makefile
0 → 100644
View file @
24824a0e
#
# Makefile for the kernel SAA7146 FULL TS DVB device driver
# and the AV7110 DVB device driver
#
dvb-ttpci-budget-objs
:=
budget.o
dvb-ttpci-budget-av-objs
:=
budget-av.o
dvb-ttpci-budget-ci-objs
:=
budget-ci.o
dvb-ttpci-budget-patch-objs
:=
budget-patch.o
dvb-ttpci-objs
:=
av7110.o av7110_ipack.o av7110_ir.o
obj-$(CONFIG_DVB_BUDGET)
+=
budget-core.o dvb-ttpci-budget.o
obj-$(CONFIG_DVB_BUDGET_CI)
+=
budget-core.o dvb-ttpci-budget-ci.o
obj-$(CONFIG_DVB_BUDGET_AV)
+=
budget-core.o dvb-ttpci-budget-av.o
obj-$(CONFIG_DVB_BUDGET_PATCH)
+=
budget-core.o dvb-ttpci-budget-patch.o
obj-$(CONFIG_DVB_AV7110)
+=
dvb-ttpci.o
EXTRA_CFLAGS
=
-Idrivers
/media/dvb/dvb-core/
drivers/media/dvb/ttpci/av7110.c
0 → 100644
View file @
24824a0e
This source diff could not be displayed because it is too large. You can
view the blob
instead.
drivers/media/dvb/ttpci/av7110.h
0 → 100644
View file @
24824a0e
This diff is collapsed.
Click to expand it.
drivers/media/dvb/ttpci/av7110_firm.h
0 → 100644
View file @
24824a0e
This diff is collapsed.
Click to expand it.
drivers/media/dvb/ttpci/av7110_ipack.c
0 → 100644
View file @
24824a0e
#include "dvb_filter.h"
#include "av7110_ipack.h"
#include <linux/string.h>
/* for memcpy() */
void
av7110_ipack_reset
(
ipack
*
p
)
{
p
->
found
=
0
;
p
->
cid
=
0
;
p
->
plength
=
0
;
p
->
flag1
=
0
;
p
->
flag2
=
0
;
p
->
hlength
=
0
;
p
->
mpeg
=
0
;
p
->
check
=
0
;
p
->
which
=
0
;
p
->
done
=
0
;
p
->
count
=
0
;
}
void
av7110_ipack_init
(
ipack
*
p
,
int
size
,
void
(
*
func
)(
u8
*
buf
,
int
size
,
void
*
priv
))
{
if
(
!
(
p
->
buf
=
vmalloc
(
size
*
sizeof
(
u8
)))
){
printk
(
"Couldn't allocate memory for ipack
\n
"
);
}
p
->
size
=
size
;
p
->
func
=
func
;
p
->
repack_subids
=
0
;
av7110_ipack_reset
(
p
);
}
void
av7110_ipack_free
(
ipack
*
p
)
{
if
(
p
->
buf
)
vfree
(
p
->
buf
);
}
static
void
send_ipack
(
ipack
*
p
)
{
int
off
;
AudioInfo
ai
;
int
ac3_off
=
0
;
int
streamid
=
0
;
int
nframes
=
0
;
int
f
=
0
;
switch
(
p
->
mpeg
){
case
2
:
if
(
p
->
count
<
10
)
return
;
p
->
buf
[
3
]
=
p
->
cid
;
p
->
buf
[
4
]
=
(
u8
)(((
p
->
count
-
6
)
&
0xFF00
)
>>
8
);
p
->
buf
[
5
]
=
(
u8
)((
p
->
count
-
6
)
&
0x00FF
);
if
(
p
->
repack_subids
&&
p
->
cid
==
PRIVATE_STREAM1
){
off
=
9
+
p
->
buf
[
8
];
streamid
=
p
->
buf
[
off
];
if
((
streamid
&
0xF8
)
==
0x80
){
ai
.
off
=
0
;
ac3_off
=
((
p
->
buf
[
off
+
2
]
<<
8
)
|
p
->
buf
[
off
+
3
]);
if
(
ac3_off
<
p
->
count
)
f
=
dvb_filter_get_ac3info
(
p
->
buf
+
off
+
3
+
ac3_off
,
p
->
count
-
ac3_off
,
&
ai
,
0
);
if
(
!
f
){
nframes
=
(
p
->
count
-
off
-
3
-
ac3_off
)
/
ai
.
framesize
+
1
;
p
->
buf
[
off
+
2
]
=
(
ac3_off
>>
8
)
&
0xFF
;
p
->
buf
[
off
+
3
]
=
(
ac3_off
)
&
0xFF
;
p
->
buf
[
off
+
1
]
=
nframes
;
ac3_off
+=
nframes
*
ai
.
framesize
-
p
->
count
;
}
}
}
p
->
func
(
p
->
buf
,
p
->
count
,
p
->
data
);
p
->
buf
[
6
]
=
0x80
;
p
->
buf
[
7
]
=
0x00
;
p
->
buf
[
8
]
=
0x00
;
p
->
count
=
9
;
if
(
p
->
repack_subids
&&
p
->
cid
==
PRIVATE_STREAM1
&&
(
streamid
&
0xF8
)
==
0x80
){
p
->
count
+=
4
;
p
->
buf
[
9
]
=
streamid
;
p
->
buf
[
10
]
=
(
ac3_off
>>
8
)
&
0xFF
;
p
->
buf
[
11
]
=
(
ac3_off
)
&
0xFF
;
p
->
buf
[
12
]
=
0
;
}
break
;
case
1
:
if
(
p
->
count
<
8
)
return
;
p
->
buf
[
3
]
=
p
->
cid
;
p
->
buf
[
4
]
=
(
u8
)(((
p
->
count
-
6
)
&
0xFF00
)
>>
8
);
p
->
buf
[
5
]
=
(
u8
)((
p
->
count
-
6
)
&
0x00FF
);
p
->
func
(
p
->
buf
,
p
->
count
,
p
->
data
);
p
->
buf
[
6
]
=
0x0F
;
p
->
count
=
7
;
break
;
}
}
void
av7110_ipack_flush
(
ipack
*
p
)
{
if
(
p
->
plength
!=
MMAX_PLENGTH
-
6
||
p
->
found
<=
6
)
return
;
p
->
plength
=
p
->
found
-
6
;
p
->
found
=
0
;
send_ipack
(
p
);
av7110_ipack_reset
(
p
);
}
static
void
write_ipack
(
ipack
*
p
,
const
u8
*
data
,
int
count
)
{
u8
headr
[
3
]
=
{
0x00
,
0x00
,
0x01
}
;
if
(
p
->
count
<
6
){
memcpy
(
p
->
buf
,
headr
,
3
);
p
->
count
=
6
;
}
if
(
p
->
count
+
count
<
p
->
size
){
memcpy
(
p
->
buf
+
p
->
count
,
data
,
count
);
p
->
count
+=
count
;
}
else
{
int
rest
=
p
->
size
-
p
->
count
;
memcpy
(
p
->
buf
+
p
->
count
,
data
,
rest
);
p
->
count
+=
rest
;
send_ipack
(
p
);
if
(
count
-
rest
>
0
)
write_ipack
(
p
,
data
+
rest
,
count
-
rest
);
}
}
int
av7110_ipack_instant_repack
(
const
u8
*
buf
,
int
count
,
ipack
*
p
)
{
int
l
;
int
c
=
0
;
while
(
c
<
count
&&
(
p
->
mpeg
==
0
||
(
p
->
mpeg
==
1
&&
p
->
found
<
7
)
||
(
p
->
mpeg
==
2
&&
p
->
found
<
9
))
&&
(
p
->
found
<
5
||
!
p
->
done
)){
switch
(
p
->
found
){
case
0
:
case
1
:
if
(
buf
[
c
]
==
0x00
)
p
->
found
++
;
else
p
->
found
=
0
;
c
++
;
break
;
case
2
:
if
(
buf
[
c
]
==
0x01
)
p
->
found
++
;
else
if
(
buf
[
c
]
==
0
)
{
p
->
found
=
2
;
}
else
p
->
found
=
0
;
c
++
;
break
;
case
3
:
p
->
cid
=
0
;
switch
(
buf
[
c
]){
case
PROG_STREAM_MAP
:
case
PRIVATE_STREAM2
:
case
PROG_STREAM_DIR
:
case
ECM_STREAM
:
case
EMM_STREAM
:
case
PADDING_STREAM
:
case
DSM_CC_STREAM
:
case
ISO13522_STREAM
:
p
->
done
=
1
;
case
PRIVATE_STREAM1
:
case
VIDEO_STREAM_S
...
VIDEO_STREAM_E
:
case
AUDIO_STREAM_S
...
AUDIO_STREAM_E
:
p
->
found
++
;
p
->
cid
=
buf
[
c
];
c
++
;
break
;
default:
p
->
found
=
0
;
break
;
}
break
;
case
4
:
if
(
count
-
c
>
1
){
p
->
plen
[
0
]
=
buf
[
c
];
c
++
;
p
->
plen
[
1
]
=
buf
[
c
];
c
++
;
p
->
found
+=
2
;
p
->
plength
=
(
p
->
plen
[
0
]
<<
8
)
|
p
->
plen
[
1
];
}
else
{
p
->
plen
[
0
]
=
buf
[
c
];
p
->
found
++
;
return
count
;
}
break
;
case
5
:
p
->
plen
[
1
]
=
buf
[
c
];
c
++
;
p
->
found
++
;
p
->
plength
=
(
p
->
plen
[
0
]
<<
8
)
|
p
->
plen
[
1
];
break
;
case
6
:
if
(
!
p
->
done
){
p
->
flag1
=
buf
[
c
];
c
++
;
p
->
found
++
;
if
(
(
p
->
flag1
&
0xC0
)
==
0x80
)
p
->
mpeg
=
2
;
else
{
p
->
hlength
=
0
;
p
->
which
=
0
;
p
->
mpeg
=
1
;
p
->
flag2
=
0
;
}
}
break
;
case
7
:
if
(
!
p
->
done
&&
p
->
mpeg
==
2
)
{
p
->
flag2
=
buf
[
c
];
c
++
;
p
->
found
++
;
}
break
;
case
8
:
if
(
!
p
->
done
&&
p
->
mpeg
==
2
)
{
p
->
hlength
=
buf
[
c
];
c
++
;
p
->
found
++
;
}
break
;
default:
break
;
}
}
if
(
c
==
count
)
return
count
;
if
(
!
p
->
plength
)
p
->
plength
=
MMAX_PLENGTH
-
6
;
if
(
p
->
done
||
((
p
->
mpeg
==
2
&&
p
->
found
>=
9
)
||
(
p
->
mpeg
==
1
&&
p
->
found
>=
7
))
){
switch
(
p
->
cid
){
case
AUDIO_STREAM_S
...
AUDIO_STREAM_E
:
case
VIDEO_STREAM_S
...
VIDEO_STREAM_E
:
case
PRIVATE_STREAM1
:
if
(
p
->
mpeg
==
2
&&
p
->
found
==
9
)
{
write_ipack
(
p
,
&
p
->
flag1
,
1
);
write_ipack
(
p
,
&
p
->
flag2
,
1
);
write_ipack
(
p
,
&
p
->
hlength
,
1
);
}
if
(
p
->
mpeg
==
1
&&
p
->
found
==
7
)
write_ipack
(
p
,
&
p
->
flag1
,
1
);
if
(
p
->
mpeg
==
2
&&
(
p
->
flag2
&
PTS_ONLY
)
&&
p
->
found
<
14
)
{
while
(
c
<
count
&&
p
->
found
<
14
)
{
p
->
pts
[
p
->
found
-
9
]
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
}
if
(
c
==
count
)
return
count
;
}
if
(
p
->
mpeg
==
1
&&
p
->
which
<
2000
)
{
if
(
p
->
found
==
7
)
{
p
->
check
=
p
->
flag1
;
p
->
hlength
=
1
;
}
while
(
!
p
->
which
&&
c
<
count
&&
p
->
check
==
0xFF
){
p
->
check
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
p
->
hlength
++
;
}
if
(
c
==
count
)
return
count
;
if
(
(
p
->
check
&
0xC0
)
==
0x40
&&
!
p
->
which
){
p
->
check
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
p
->
hlength
++
;
p
->
which
=
1
;
if
(
c
==
count
)
return
count
;
p
->
check
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
p
->
hlength
++
;
p
->
which
=
2
;
if
(
c
==
count
)
return
count
;
}
if
(
p
->
which
==
1
){
p
->
check
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
p
->
hlength
++
;
p
->
which
=
2
;
if
(
c
==
count
)
return
count
;
}
if
(
(
p
->
check
&
0x30
)
&&
p
->
check
!=
0xFF
){
p
->
flag2
=
(
p
->
check
&
0xF0
)
<<
2
;
p
->
pts
[
0
]
=
p
->
check
;
p
->
which
=
3
;
}
if
(
c
==
count
)
return
count
;
if
(
p
->
which
>
2
){
if
((
p
->
flag2
&
PTS_DTS_FLAGS
)
==
PTS_ONLY
){
while
(
c
<
count
&&
p
->
which
<
7
){
p
->
pts
[
p
->
which
-
2
]
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
p
->
which
++
;
p
->
hlength
++
;
}
if
(
c
==
count
)
return
count
;
}
else
if
((
p
->
flag2
&
PTS_DTS_FLAGS
)
==
PTS_DTS
){
while
(
c
<
count
&&
p
->
which
<
12
){
if
(
p
->
which
<
7
)
p
->
pts
[
p
->
which
-
2
]
=
buf
[
c
];
write_ipack
(
p
,
buf
+
c
,
1
);
c
++
;
p
->
found
++
;
p
->
which
++
;
p
->
hlength
++
;
}
if
(
c
==
count
)
return
count
;
}
p
->
which
=
2000
;
}
}
while
(
c
<
count
&&
p
->
found
<
p
->
plength
+
6
){
l
=
count
-
c
;
if
(
l
+
p
->
found
>
p
->
plength
+
6
)
l
=
p
->
plength
+
6
-
p
->
found
;
write_ipack
(
p
,
buf
+
c
,
l
);
p
->
found
+=
l
;
c
+=
l
;
}
break
;
}
if
(
p
->
done
){
if
(
p
->
found
+
count
-
c
<
p
->
plength
+
6
){
p
->
found
+=
count
-
c
;
c
=
count
;
}
else
{
c
+=
p
->
plength
+
6
-
p
->
found
;
p
->
found
=
p
->
plength
+
6
;
}
}
if
(
p
->
plength
&&
p
->
found
==
p
->
plength
+
6
)
{
send_ipack
(
p
);
av7110_ipack_reset
(
p
);
if
(
c
<
count
)
av7110_ipack_instant_repack
(
buf
+
c
,
count
-
c
,
p
);
}
}
return
count
;
}
drivers/media/dvb/ttpci/av7110_ipack.h
0 → 100644
View file @
24824a0e
#ifndef _AV7110_IPACK_H_
#define _AV7110_IPACK_H_
extern
void
av7110_ipack_init
(
ipack
*
p
,
int
size
,
void
(
*
func
)(
u8
*
buf
,
int
size
,
void
*
priv
));
extern
void
av7110_ipack_reset
(
ipack
*
p
);
extern
int
av7110_ipack_instant_repack
(
const
u8
*
buf
,
int
count
,
ipack
*
p
);
extern
void
av7110_ipack_free
(
ipack
*
p
);
extern
void
av7110_ipack_flush
(
ipack
*
p
);
#endif
drivers/media/dvb/ttpci/av7110_ir.c
0 → 100644
View file @
24824a0e
#include <asm/types.h>
#include <asm/bitops.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/proc_fs.h>
#include "av7110.h"
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include "input_fake.h"
#endif
#define UP_TIMEOUT (HZ/2)
static
int
av7110_ir_debug
=
0
;
#define dprintk(x...) do { if (av7110_ir_debug) printk (x); } while (0)
static
struct
input_dev
input_dev
;
static
u16
key_map
[
256
]
=
{
KEY_0
,
KEY_1
,
KEY_2
,
KEY_3
,
KEY_4
,
KEY_5
,
KEY_6
,
KEY_7
,
KEY_8
,
KEY_9
,
KEY_MHP
,
0
,
KEY_POWER
,
KEY_MUTE
,
0
,
KEY_INFO
,
KEY_VOLUMEUP
,
KEY_VOLUMEDOWN
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_CHANNELUP
,
KEY_CHANNELDOWN
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_TEXT
,
0
,
0
,
KEY_TV
,
0
,
0
,
0
,
0
,
0
,
KEY_SETUP
,
0
,
0
,
0
,
0
,
0
,
KEY_SUBTITLE
,
0
,
0
,
KEY_LANGUAGE
,
0
,
KEY_RADIO
,
0
,
0
,
0
,
0
,
KEY_EXIT
,
0
,
0
,
KEY_UP
,
KEY_DOWN
,
KEY_LEFT
,
KEY_RIGHT
,
KEY_OK
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_RED
,
KEY_GREEN
,
KEY_YELLOW
,
KEY_BLUE
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_MENU
,
KEY_LIST
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_UP
,
KEY_UP
,
KEY_DOWN
,
KEY_DOWN
,
0
,
0
,
0
,
0
,
KEY_EPG
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_VCR
};
static
void
av7110_emit_keyup
(
unsigned
long
data
)
{
if
(
!
data
||
!
test_bit
(
data
,
input_dev
.
key
))
return
;
input_event
(
&
input_dev
,
EV_KEY
,
data
,
!!
0
);
}
static
struct
timer_list
keyup_timer
=
{
function
:
av7110_emit_keyup
};
static
void
av7110_emit_key
(
u32
ircom
)
{
int
down
=
ircom
&
(
0x80000000
);
u16
keycode
=
key_map
[
ircom
&
0xff
];
dprintk
(
"#########%08x######### key %02x %s (keycode %i)
\n
"
,
ircom
,
ircom
&
0xff
,
down
?
"pressed"
:
"released"
,
keycode
);
if
(
!
keycode
)
{
printk
(
"%s: unknown key 0x%02x!!
\n
"
,
__FUNCTION__
,
ircom
&
0xff
);
return
;
}
if
(
timer_pending
(
&
keyup_timer
))
{
del_timer
(
&
keyup_timer
);
if
(
keyup_timer
.
data
!=
keycode
)
input_event
(
&
input_dev
,
EV_KEY
,
keyup_timer
.
data
,
!!
0
);
}
clear_bit
(
keycode
,
input_dev
.
key
);
input_event
(
&
input_dev
,
EV_KEY
,
keycode
,
!
0
);
keyup_timer
.
expires
=
jiffies
+
UP_TIMEOUT
;
keyup_timer
.
data
=
keycode
;
add_timer
(
&
keyup_timer
);
}
static
void
input_register_keys
(
void
)
{
int
i
;
memset
(
input_dev
.
keybit
,
0
,
sizeof
(
input_dev
.
keybit
));
for
(
i
=
0
;
i
<
sizeof
(
key_map
)
/
sizeof
(
key_map
[
0
]);
i
++
)
{
if
(
key_map
[
i
]
>
KEY_MAX
)
key_map
[
i
]
=
0
;
else
if
(
key_map
[
i
]
>
KEY_RESERVED
)
set_bit
(
key_map
[
i
],
input_dev
.
keybit
);
}
}
static
int
av7110_ir_write_proc
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
u32
ir_config
;
if
(
count
<
4
+
256
*
sizeof
(
u16
))
return
-
EINVAL
;
memcpy
(
&
ir_config
,
buffer
,
4
);
memcpy
(
&
key_map
,
buffer
+
4
,
256
*
sizeof
(
u16
));
av7110_setup_irc_config
(
NULL
,
ir_config
);
input_register_keys
();
return
count
;
}
int
__init
av7110_ir_init
(
void
)
{
static
struct
proc_dir_entry
*
e
;
init_timer
(
&
keyup_timer
);
keyup_timer
.
data
=
0
;
input_dev
.
name
=
"DVB on-card IR receiver"
;
/**
* enable keys
*/
set_bit
(
EV_KEY
,
input_dev
.
evbit
);
input_register_keys
();
input_register_device
(
&
input_dev
);
av7110_setup_irc_config
(
NULL
,
0x0001
);
av7110_register_irc_handler
(
av7110_emit_key
);
e
=
create_proc_entry
(
"av7110_ir"
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
NULL
);
if
(
e
)
{
e
->
write_proc
=
av7110_ir_write_proc
;
e
->
size
=
4
+
256
*
sizeof
(
u16
);
}
return
0
;
}
void
__exit
av7110_ir_exit
(
void
)
{
remove_proc_entry
(
"av7110_ir"
,
NULL
);
av7110_unregister_irc_handler
(
av7110_emit_key
);
input_unregister_device
(
&
input_dev
);
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
//MODULE_LICENSE("GPL");
MODULE_PARM
(
av7110_ir_debug
,
"i"
);
MODULE_PARM_DESC
(
av7110_ir_debug
,
"enable AV7110 IR receiver debug messages"
);
drivers/media/dvb/ttpci/budget-av.c
0 → 100644
View file @
24824a0e
/*
* budget-av.c: driver for the SAA7146 based Budget DVB cards
* with analog video in
*
* Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
* Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
#include "budget.h"
#include <media/saa7146_vv.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#define KBUILD_MODNAME budget_av
#endif
struct
budget_av
{
struct
budget
budget
;
struct
video_device
vd
;
int
cur_input
;
};
/****************************************************************************
* INITIALIZATION
****************************************************************************/
static
inline
void
ddelay
(
int
i
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
((
HZ
*
i
)
/
100
);
}
static
u8
i2c_readreg
(
struct
dvb_i2c_bus
*
i2c
,
u8
id
,
u8
reg
)
{
u8
mm1
[]
=
{
0x00
};
u8
mm2
[]
=
{
0x00
};
struct
i2c_msg
msgs
[
2
];
msgs
[
0
].
flags
=
0
;
msgs
[
1
].
flags
=
I2C_M_RD
;
msgs
[
0
].
addr
=
msgs
[
1
].
addr
=
id
/
2
;
mm1
[
0
]
=
reg
;
msgs
[
0
].
len
=
1
;
msgs
[
1
].
len
=
1
;
msgs
[
0
].
buf
=
mm1
;
msgs
[
1
].
buf
=
mm2
;
i2c
->
xfer
(
i2c
,
msgs
,
2
);
return
mm2
[
0
];
}
static
int
i2c_writereg
(
struct
dvb_i2c_bus
*
i2c
,
u8
id
,
u8
reg
,
u8
val
)
{
u8
msg
[
2
]
=
{
reg
,
val
};
struct
i2c_msg
msgs
;
msgs
.
flags
=
0
;
msgs
.
addr
=
id
/
2
;
msgs
.
len
=
2
;
msgs
.
buf
=
msg
;
return
i2c
->
xfer
(
i2c
,
&
msgs
,
1
);
}
static
const
u8
saa7113_tab
[]
=
{
0x01
,
0x08
,
0x02
,
0xc0
,
0x03
,
0x33
,
0x04
,
0x00
,
0x05
,
0x00
,
0x06
,
0xeb
,
0x07
,
0xe0
,
0x08
,
0x28
,
0x09
,
0x00
,
0x0a
,
0x80
,
0x0b
,
0x47
,
0x0c
,
0x40
,
0x0d
,
0x00
,
0x0e
,
0x01
,
0x0f
,
0x44
,
0x10
,
0x08
,
0x11
,
0x0c
,
0x12
,
0x7b
,
0x13
,
0x00
,
0x15
,
0x00
,
0x16
,
0x00
,
0x17
,
0x00
,
0x57
,
0xff
,
0x40
,
0x82
,
0x58
,
0x00
,
0x59
,
0x54
,
0x5a
,
0x07
,
0x5b
,
0x83
,
0x5e
,
0x00
,
0xff
};
static
int
saa7113_init
(
struct
budget_av
*
budget_av
)
{
struct
budget
*
budget
=
&
budget_av
->
budget
;
const
u8
*
data
=
saa7113_tab
;
if
(
i2c_writereg
(
budget
->
i2c_bus
,
0x4a
,
0x01
,
0x08
)
!=
1
)
{
DEB_D
((
"saa7113: not found on KNC card
\n
"
));
return
-
ENODEV
;
}
INFO
((
"saa7113: detected and initializing
\n
"
));
while
(
*
data
!=
0xff
)
{
i2c_writereg
(
budget
->
i2c_bus
,
0x4a
,
*
data
,
*
(
data
+
1
));
data
+=
2
;
}
DEB_D
((
"saa7113: status=%02x
\n
"
,
i2c_readreg
(
budget
->
i2c_bus
,
0x4a
,
0x1f
)));
return
0
;
}
static
int
saa7113_setinput
(
struct
budget_av
*
budget_av
,
int
input
)
{
struct
budget
*
budget
=
&
budget_av
->
budget
;
if
(
input
==
1
)
{
i2c_writereg
(
budget
->
i2c_bus
,
0x4a
,
0x02
,
0xc7
);
i2c_writereg
(
budget
->
i2c_bus
,
0x4a
,
0x09
,
0x80
);
}
else
if
(
input
==
0
)
{
i2c_writereg
(
budget
->
i2c_bus
,
0x4a
,
0x02
,
0xc0
);
i2c_writereg
(
budget
->
i2c_bus
,
0x4a
,
0x09
,
0x00
);
}
else
return
-
EINVAL
;
budget_av
->
cur_input
=
input
;
return
0
;
}
static
int
budget_av_detach
(
struct
saa7146_dev
*
dev
)
{
struct
budget_av
*
budget_av
=
(
struct
budget_av
*
)
dev
->
ext_priv
;
int
err
;
DEB_EE
((
"dev: %p
\n
"
,
dev
));
saa7146_setgpio
(
dev
,
0
,
SAA7146_GPIO_OUTLO
);
ddelay
(
20
);
saa7146_unregister_device
(
&
budget_av
->
vd
,
dev
);
err
=
ttpci_budget_deinit
(
&
budget_av
->
budget
);
kfree
(
budget_av
);
return
err
;
}
static
int
budget_av_attach
(
struct
saa7146_dev
*
dev
,
struct
saa7146_pci_extension_data
*
info
)
{
struct
budget_av
*
budget_av
;
struct
budget_info
*
bi
=
info
->
ext_priv
;
int
err
;
DEB_EE
((
"dev: %p
\n
"
,
dev
));
if
(
bi
->
type
!=
BUDGET_KNC1
)
{
return
-
ENODEV
;
}
if
(
!
(
budget_av
=
kmalloc
(
sizeof
(
struct
budget_av
),
GFP_KERNEL
)))
return
-
ENOMEM
;
memset
(
budget_av
,
0
,
sizeof
(
struct
budget_av
));
if
((
err
=
ttpci_budget_init
(
&
budget_av
->
budget
,
dev
,
info
)))
{
kfree
(
budget_av
);
return
err
;
}
dev
->
ext_priv
=
budget_av
;
/* knc1 initialization */
saa7146_write
(
dev
,
DD1_STREAM_B
,
0x04000000
);
saa7146_write
(
dev
,
DD1_INIT
,
0x07000600
);
saa7146_write
(
dev
,
MC2
,
MASK_09
|
MASK_25
|
MASK_10
|
MASK_26
);
//test_knc_ci(av7110);
saa7146_setgpio
(
dev
,
0
,
SAA7146_GPIO_OUTHI
);
ddelay
(
50
);
if
((
err
=
saa7113_init
(
budget_av
)))
{
budget_av_detach
(
dev
);
return
err
;
}
saa7146_vv_init
(
dev
);
if
((
err
=
saa7146_register_device
(
&
budget_av
->
vd
,
dev
,
"knc1"
,
VFL_TYPE_GRABBER
)))
{
ERR
((
"cannot register capture v4l2 device.
\n
"
));
budget_av_detach
(
dev
);
return
err
;
}
/* beware: this modifies dev->vv ... */
saa7146_set_hps_source_and_sync
(
dev
,
SAA7146_HPS_SOURCE_PORT_A
,
SAA7146_HPS_SYNC_PORT_A
);
saa7113_setinput
(
budget_av
,
0
);
/* what is this? since we don't support open()/close()
notifications, we simply put this into the release handler... */
// saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
ddelay
(
20
);
/* fixme: find some sane values here... */
saa7146_write
(
dev
,
PCI_BT_V1
,
0x1c00101f
);
return
0
;
}
#define KNC1_INPUTS 2
static
struct
v4l2_input
knc1_inputs
[
KNC1_INPUTS
]
=
{
{
0
,
"Composite"
,
V4L2_INPUT_TYPE_TUNER
,
1
,
0
,
V4L2_STD_PAL_BG
|
V4L2_STD_NTSC_M
,
0
},
{
1
,
"S-Video"
,
V4L2_INPUT_TYPE_CAMERA
,
2
,
0
,
V4L2_STD_PAL_BG
|
V4L2_STD_NTSC_M
,
0
},
};
static
struct
saa7146_extension_ioctls
ioctls
[]
=
{
{
VIDIOC_ENUMINPUT
,
SAA7146_EXCLUSIVE
},
{
VIDIOC_G_INPUT
,
SAA7146_EXCLUSIVE
},
{
VIDIOC_S_INPUT
,
SAA7146_EXCLUSIVE
},
{
0
,
0
}
};
static
int
av_ioctl
(
struct
saa7146_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
)
{
struct
budget_av
*
budget_av
=
(
struct
budget_av
*
)
dev
->
ext_priv
;
/*
struct saa7146_vv *vv = dev->vv_data;
*/
switch
(
cmd
)
{
case
VIDIOC_ENUMINPUT
:
{
struct
v4l2_input
*
i
=
arg
;
DEB_EE
((
"VIDIOC_ENUMINPUT %d.
\n
"
,
i
->
index
));
if
(
i
->
index
<
0
||
i
->
index
>=
KNC1_INPUTS
)
{
return
-
EINVAL
;
}
memcpy
(
i
,
&
knc1_inputs
[
i
->
index
],
sizeof
(
struct
v4l2_input
));
return
0
;
}
case
VIDIOC_G_INPUT
:
{
int
*
input
=
(
int
*
)
arg
;
*
input
=
budget_av
->
cur_input
;
DEB_EE
((
"VIDIOC_G_INPUT %d.
\n
"
,
*
input
));
return
0
;
}
case
VIDIOC_S_INPUT
:
{
int
input
=
*
(
int
*
)
arg
;
DEB_EE
((
"VIDIOC_S_INPUT %d.
\n
"
,
input
));
return
saa7113_setinput
(
budget_av
,
input
);
}
default:
/*
DEB2(printk("does not handle this ioctl.\n"));
*/
return
-
ENOIOCTLCMD
;
}
return
0
;
}
static
struct
saa7146_standard
standard
[]
=
{
{
"PAL"
,
V4L2_STD_PAL
,
SAA7146_PAL_VALUES
},
{
"NTSC"
,
V4L2_STD_NTSC
,
SAA7146_NTSC_VALUES
},
};
static
struct
saa7146_ext_vv
vv_data
=
{
.
inputs
=
2
,
.
capabilities
=
0
,
// perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
.
flags
=
0
,
.
stds
=
&
standard
[
0
],
.
num_stds
=
sizeof
(
standard
)
/
sizeof
(
struct
saa7146_standard
),
.
ioctls
=
&
ioctls
[
0
],
.
ioctl
=
av_ioctl
,
};
static
struct
saa7146_extension
budget_extension
;
MAKE_BUDGET_INFO
(
knc1
,
"KNC1 DVB-S"
,
BUDGET_KNC1
);
static
struct
pci_device_id
pci_tbl
[]
=
{
MAKE_EXTENSION_PCI
(
knc1
,
0x1131
,
0x4f56
),
{
.
vendor
=
0
,
}
};
static
struct
saa7146_extension
budget_extension
=
{
.
name
=
"budget dvb /w video in
\0
"
,
.
pci_tbl
=
pci_tbl
,
.
module
=
THIS_MODULE
,
.
attach
=
budget_av_attach
,
.
detach
=
budget_av_detach
,
.
ext_vv_data
=
&
vv_data
,
.
irq_mask
=
MASK_10
,
.
irq_func
=
ttpci_budget_irq10_handler
,
};
static
int
__init
budget_av_init
(
void
)
{
DEB_EE
((
".
\n
"
));
if
(
saa7146_register_extension
(
&
budget_extension
))
return
-
ENODEV
;
return
0
;
}
static
void
__exit
budget_av_exit
(
void
)
{
DEB_EE
((
".
\n
"
));
saa7146_unregister_extension
(
&
budget_extension
);
}
module_init
(
budget_av_init
);
module_exit
(
budget_av_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Ralph Metzler, Marcus Metzler, Michael Hunold, others"
);
MODULE_DESCRIPTION
(
"driver for the SAA7146 based so-called "
"budget PCI DVB w/ analog input (e.g. the KNC cards)"
);
drivers/media/dvb/ttpci/budget-ci.c
0 → 100644
View file @
24824a0e
/*
* budget-ci.c: driver for the SAA7146 based Budget DVB cards
*
* Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
* partially based on the Siemens DVB driver by Ralph+Marcus Metzler
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
#include "budget.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#define KBUILD_MODNAME budget
#endif
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include "input_fake.h"
#endif
struct
budget_ci
{
struct
budget
budget
;
struct
input_dev
input_dev
;
struct
tasklet_struct
msp430_irq_tasklet
;
};
#ifndef BORROWED_FROM_AV7110_H_BUT_REALLY_BELONGS_IN_SAA7146_DEFS_H
#define DEBINOSWAP 0x000e0000
#define GPIO_IRQHI 0x10
#define GPIO_INPUT 0x00
void
gpio_set
(
struct
saa7146_dev
*
saa
,
u8
pin
,
u8
data
)
{
u32
value
=
0
;
/* sanity check */
if
(
pin
>
3
)
return
;
/* read old register contents */
value
=
saa7146_read
(
saa
,
GPIO_CTRL
);
value
&=
~
(
0xff
<<
(
8
*
pin
));
value
|=
(
data
<<
(
8
*
pin
));
saa7146_write
(
saa
,
GPIO_CTRL
,
value
);
}
static
int
wait_for_debi_done
(
struct
saa7146_dev
*
saa
)
{
int
start
=
jiffies
;
/* wait for registers to be programmed */
while
(
1
)
{
if
(
saa7146_read
(
saa
,
MC2
)
&
2
)
break
;
if
(
jiffies
-
start
>
HZ
/
20
)
{
printk
(
"DVB (%s): timed out while waiting"
" for registers getting programmed
\n
"
,
__FUNCTION__
);
return
-
ETIMEDOUT
;
}
}
/* wait for transfer to complete */
start
=
jiffies
;
while
(
1
)
{
if
(
!
(
saa7146_read
(
saa
,
PSR
)
&
SPCI_DEBI_S
))
break
;
saa7146_read
(
saa
,
MC2
);
if
(
jiffies
-
start
>
HZ
/
4
)
{
printk
(
"DVB (%s): timed out while waiting"
" for transfer completion
\n
"
,
__FUNCTION__
);
return
-
ETIMEDOUT
;
}
}
return
0
;
}
static
u32
debiread
(
struct
saa7146_dev
*
saa
,
u32
config
,
int
addr
,
int
count
)
{
u32
result
=
0
;
if
(
count
>
4
||
count
<=
0
)
return
0
;
if
(
wait_for_debi_done
(
saa
)
<
0
)
return
0
;
saa7146_write
(
saa
,
DEBI_COMMAND
,
(
count
<<
17
)
|
0x10000
|
(
addr
&
0xffff
));
saa7146_write
(
saa
,
DEBI_CONFIG
,
config
);
saa7146_write
(
saa
,
MC2
,
(
2
<<
16
)
|
2
);
wait_for_debi_done
(
saa
);
result
=
saa7146_read
(
saa
,
DEBI_AD
);
result
&=
(
0xffffffffUL
>>
((
4
-
count
)
*
8
));
return
result
;
}
/* DEBI during interrupt */
static
inline
u32
irdebi
(
struct
saa7146_dev
*
saa
,
u32
config
,
int
addr
,
u32
val
,
int
count
)
{
u32
res
;
res
=
debiread
(
saa
,
config
,
addr
,
count
);
return
res
;
}
#endif
/* from reading the following remotes:
Zenith Universal 7 / TV Mode 807 / VCR Mode 837
Hauppauge (from NOVA-CI-s box product)
i've taken a "middle of the road" approach and note the differences
*/
static
u16
key_map
[
64
]
=
{
/* 0x0X */
KEY_0
,
KEY_1
,
KEY_2
,
KEY_3
,
KEY_4
,
KEY_5
,
KEY_6
,
KEY_7
,
KEY_8
,
KEY_9
,
KEY_ENTER
,
0
,
KEY_POWER
,
/* RADIO on Hauppauge */
KEY_MUTE
,
0
,
KEY_A
,
/* TV on Hauppauge */
/* 0x1X */
KEY_VOLUMEUP
,
KEY_VOLUMEDOWN
,
0
,
0
,
KEY_B
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
KEY_UP
,
KEY_DOWN
,
KEY_OPTION
,
/* RESERVED on Hauppauge */
0
,
/* 0x2X */
KEY_CHANNELUP
,
KEY_CHANNELDOWN
,
KEY_PREVIOUS
,
/* Prev. Ch on Zenith, SOURCE on Hauppauge */
0
,
0
,
0
,
KEY_CYCLEWINDOWS
,
/* MINIMIZE on Hauppauge */
0
,
KEY_ENTER
,
/* VCR mode on Zenith */
KEY_PAUSE
,
0
,
KEY_RIGHT
,
KEY_LEFT
,
0
,
KEY_MENU
,
/* FULL SCREEN on Hauppauge */
0
,
/* 0x3X */
0
,
KEY_PREVIOUS
,
/* VCR mode on Zenith */
KEY_REWIND
,
0
,
KEY_FASTFORWARD
,
KEY_PLAY
,
KEY_STOP
,
KEY_RECORD
,
KEY_TUNER
,
/* TV/VCR on Zenith */
0
,
KEY_C
,
0
,
KEY_EXIT
,
0
,
KEY_TUNER
,
/* VCR mode on Zenith */
0
,
};
static
void
msp430_ir_debounce
(
unsigned
long
data
)
{
struct
input_dev
*
dev
=
(
struct
input_dev
*
)
data
;
if
(
dev
->
rep
[
0
]
==
0
||
dev
->
rep
[
0
]
==
~
0
)
{
input_event
(
dev
,
EV_KEY
,
key_map
[
dev
->
repeat_key
],
!!
0
);
return
;
}
dev
->
rep
[
0
]
=
0
;
dev
->
timer
.
expires
=
jiffies
+
HZ
*
350
/
1000
;
add_timer
(
&
dev
->
timer
);
input_event
(
dev
,
EV_KEY
,
key_map
[
dev
->
repeat_key
],
2
);
/* REPEAT */
}
static
void
msp430_ir_interrupt
(
unsigned
long
data
)
{
struct
budget_ci
*
budget_ci
=
(
struct
budget_ci
*
)
data
;
struct
saa7146_dev
*
saa
=
budget_ci
->
budget
.
dev
;
struct
input_dev
*
dev
=
&
budget_ci
->
input_dev
;
unsigned
int
code
=
irdebi
(
saa
,
DEBINOSWAP
,
0x1234
,
0
,
2
)
>>
8
;
if
(
code
&
0x40
)
{
code
&=
0x3f
;
if
(
timer_pending
(
&
dev
->
timer
))
{
if
(
code
==
dev
->
repeat_key
)
{
++
dev
->
rep
[
0
];
return
;
}
del_timer
(
&
dev
->
timer
);
input_event
(
dev
,
EV_KEY
,
key_map
[
dev
->
repeat_key
],
!!
0
);
}
if
(
!
key_map
[
code
])
{
printk
(
"DVB (%s): no key for %02x!
\n
"
,
__FUNCTION__
,
code
);
return
;
}
/* initialize debounce and repeat */
dev
->
repeat_key
=
code
;
/* Zenith remote _always_ sends 2 sequences */
dev
->
rep
[
0
]
=
~
0
;
/* 350 milliseconds */
dev
->
timer
.
expires
=
jiffies
+
HZ
*
350
/
1000
;
/* MAKE */
input_event
(
dev
,
EV_KEY
,
key_map
[
code
],
!
0
);
add_timer
(
&
dev
->
timer
);
}
}
static
int
msp430_ir_init
(
struct
budget_ci
*
budget_ci
)
{
struct
saa7146_dev
*
saa
=
budget_ci
->
budget
.
dev
;
int
i
;
memset
(
&
budget_ci
->
input_dev
,
0
,
sizeof
(
struct
input_dev
));
budget_ci
->
input_dev
.
name
=
saa
->
name
;
set_bit
(
EV_KEY
,
budget_ci
->
input_dev
.
evbit
);
for
(
i
=
0
;
i
<
sizeof
(
key_map
)
/
sizeof
(
*
key_map
);
i
++
)
if
(
key_map
[
i
])
set_bit
(
key_map
[
i
],
budget_ci
->
input_dev
.
keybit
);
input_register_device
(
&
budget_ci
->
input_dev
);
budget_ci
->
input_dev
.
timer
.
function
=
msp430_ir_debounce
;
saa7146_write
(
saa
,
IER
,
saa7146_read
(
saa
,
IER
)
|
MASK_06
);
gpio_set
(
saa
,
3
,
GPIO_IRQHI
);
return
0
;
}
static
void
msp430_ir_deinit
(
struct
budget_ci
*
budget_ci
)
{
struct
saa7146_dev
*
saa
=
budget_ci
->
budget
.
dev
;
struct
input_dev
*
dev
=
&
budget_ci
->
input_dev
;
saa7146_write
(
saa
,
IER
,
saa7146_read
(
saa
,
IER
)
&
~
MASK_06
);
gpio_set
(
saa
,
3
,
GPIO_INPUT
);
gpio_set
(
saa
,
2
,
GPIO_INPUT
);
if
(
del_timer
(
&
dev
->
timer
))
input_event
(
dev
,
EV_KEY
,
key_map
[
dev
->
repeat_key
],
!!
0
);
input_unregister_device
(
dev
);
}
static
void
budget_ci_irq
(
struct
saa7146_dev
*
dev
,
u32
*
isr
)
{
struct
budget_ci
*
budget_ci
=
(
struct
budget_ci
*
)
dev
->
ext_priv
;
DEB_EE
((
"dev: %p, budget_ci: %p
\n
"
,
dev
,
budget_ci
));
if
(
*
isr
&
MASK_06
)
tasklet_schedule
(
&
budget_ci
->
msp430_irq_tasklet
);
if
(
*
isr
&
MASK_10
)
ttpci_budget_irq10_handler
(
dev
,
isr
);
}
static
int
budget_ci_attach
(
struct
saa7146_dev
*
dev
,
struct
saa7146_pci_extension_data
*
info
)
{
struct
budget_ci
*
budget_ci
;
int
err
;
if
(
!
(
budget_ci
=
kmalloc
(
sizeof
(
struct
budget_ci
),
GFP_KERNEL
)))
return
-
ENOMEM
;
DEB_EE
((
"budget_ci: %p
\n
"
,
budget_ci
));
if
((
err
=
ttpci_budget_init
(
&
budget_ci
->
budget
,
dev
,
info
)))
{
kfree
(
budget_ci
);
return
err
;
}
dev
->
ext_priv
=
budget_ci
;
tasklet_init
(
&
budget_ci
->
msp430_irq_tasklet
,
msp430_ir_interrupt
,
(
unsigned
long
)
budget_ci
);
msp430_ir_init
(
budget_ci
);
return
0
;
}
static
int
budget_ci_detach
(
struct
saa7146_dev
*
dev
)
{
struct
budget_ci
*
budget_ci
=
(
struct
budget_ci
*
)
dev
->
ext_priv
;
int
err
;
err
=
ttpci_budget_deinit
(
&
budget_ci
->
budget
);
tasklet_kill
(
&
budget_ci
->
msp430_irq_tasklet
);
msp430_ir_deinit
(
budget_ci
);
kfree
(
budget_ci
);
return
err
;
}
static
struct
saa7146_extension
budget_extension
;
MAKE_BUDGET_INFO
(
ttbci
,
"TT-Budget/WinTV-NOVA-CI PCI"
,
BUDGET_TT_HW_DISEQC
);
static
struct
pci_device_id
pci_tbl
[]
=
{
MAKE_EXTENSION_PCI
(
ttbci
,
0x13c2
,
0x100c
),
MAKE_EXTENSION_PCI
(
ttbci
,
0x13c2
,
0x100f
),
{
.
vendor
=
0
,
}
};
static
struct
saa7146_extension
budget_extension
=
{
.
name
=
"budget_ci dvb
\0
"
,
.
flags
=
0
,
.
ext_vv_data
=
NULL
,
.
module
=
THIS_MODULE
,
.
pci_tbl
=
&
pci_tbl
[
0
],
.
attach
=
budget_ci_attach
,
.
detach
=
budget_ci_detach
,
.
irq_mask
=
MASK_06
|
MASK_10
,
.
irq_func
=
budget_ci_irq
,
};
static
int
__init
budget_ci_init
(
void
)
{
if
(
saa7146_register_extension
(
&
budget_extension
))
return
-
ENODEV
;
return
0
;
}
static
void
__exit
budget_ci_exit
(
void
)
{
DEB_EE
((
".
\n
"
));
saa7146_unregister_extension
(
&
budget_extension
);
}
module_init
(
budget_ci_init
);
module_exit
(
budget_ci_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Michael Hunold, Jack Thomasson, others"
);
MODULE_DESCRIPTION
(
"driver for the SAA7146 based so-called "
"budget PCI DVB cards w/ CI-module produced by "
"Siemens, Technotrend, Hauppauge"
);
drivers/media/dvb/ttpci/budget-core.c
0 → 100644
View file @
24824a0e
#include "budget.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#define KBUILD_MODNAME budget
#endif
int
budget_debug
=
0
;
/****************************************************************************
* General helper functions
****************************************************************************/
static
inline
void
ddelay
(
int
i
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
((
HZ
*
i
)
/
100
);
}
/****************************************************************************
* TT budget / WinTV Nova
****************************************************************************/
static
int
stop_ts_capture
(
struct
budget
*
budget
)
{
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
(
--
budget
->
feeding
)
return
budget
->
feeding
;
saa7146_write
(
budget
->
dev
,
MC1
,
MASK_20
);
// DMA3 off
IER_DISABLE
(
budget
->
dev
,
MASK_10
);
return
0
;
}
static
int
start_ts_capture
(
struct
budget
*
budget
)
{
struct
saa7146_dev
*
dev
=
budget
->
dev
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
(
budget
->
feeding
)
return
++
budget
->
feeding
;
saa7146_write
(
dev
,
MC1
,
MASK_20
);
// DMA3 off
memset
(
budget
->
grabbing
,
0x00
,
TS_HEIGHT
*
TS_WIDTH
);
saa7146_write
(
dev
,
PCI_BT_V1
,
0x001c0000
|
(
saa7146_read
(
dev
,
PCI_BT_V1
)
&
~
0x001f0000
));
budget
->
tsf
=
0xff
;
budget
->
ttbp
=
0
;
saa7146_write
(
dev
,
DD1_INIT
,
0x02000600
);
saa7146_write
(
dev
,
MC2
,
(
MASK_09
|
MASK_25
|
MASK_10
|
MASK_26
));
saa7146_write
(
dev
,
BRS_CTRL
,
0x60000000
);
saa7146_write
(
dev
,
MC2
,
(
MASK_08
|
MASK_24
));
mdelay
(
10
);
saa7146_write
(
dev
,
BASE_ODD3
,
0
);
saa7146_write
(
dev
,
BASE_EVEN3
,
TS_WIDTH
*
TS_HEIGHT
/
2
);
saa7146_write
(
dev
,
PROT_ADDR3
,
TS_WIDTH
*
TS_HEIGHT
);
saa7146_write
(
dev
,
BASE_PAGE3
,
budget
->
pt
.
dma
|
ME1
|
0x90
);
saa7146_write
(
dev
,
PITCH3
,
TS_WIDTH
);
saa7146_write
(
dev
,
NUM_LINE_BYTE3
,
((
TS_HEIGHT
/
2
)
<<
16
)
|
TS_WIDTH
);
saa7146_write
(
dev
,
MC2
,
(
MASK_04
|
MASK_20
));
saa7146_write
(
dev
,
MC1
,
(
MASK_04
|
MASK_20
));
// DMA3 on
IER_ENABLE
(
budget
->
dev
,
MASK_10
);
// VPE
return
++
budget
->
feeding
;
}
static
void
vpeirq
(
unsigned
long
data
)
{
struct
budget
*
budget
=
(
struct
budget
*
)
data
;
u8
*
mem
=
(
u8
*
)(
budget
->
grabbing
);
u32
olddma
=
budget
->
ttbp
;
u32
newdma
=
saa7146_read
(
budget
->
dev
,
PCI_VDP3
);
/* nearest lower position divisible by 188 */
newdma
-=
newdma
%
188
;
if
(
newdma
>=
TS_BUFLEN
)
return
;
budget
->
ttbp
=
newdma
;
if
(
budget
->
feeding
==
0
||
newdma
==
olddma
)
return
;
if
(
newdma
>
olddma
)
{
/* no wraparound, dump olddma..newdma */
if
(
mem
[
olddma
]
==
0x47
)
dvb_dmx_swfilter_packets
(
&
budget
->
demux
,
mem
+
olddma
,
(
newdma
-
olddma
)
/
188
);
}
else
{
/* wraparound, dump olddma..buflen and 0..newdma */
if
(
mem
[
olddma
]
==
0x47
)
dvb_dmx_swfilter_packets
(
&
budget
->
demux
,
mem
+
olddma
,
(
TS_BUFLEN
-
olddma
)
/
188
);
if
(
mem
[
0
]
==
0x47
)
dvb_dmx_swfilter_packets
(
&
budget
->
demux
,
mem
,
newdma
/
188
);
}
}
/****************************************************************************
* DVB API SECTION
****************************************************************************/
static
int
budget_start_feed
(
struct
dvb_demux_feed
*
feed
)
{
struct
dvb_demux
*
demux
=
feed
->
demux
;
struct
budget
*
budget
=
(
struct
budget
*
)
demux
->
priv
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
(
!
demux
->
dmx
.
frontend
)
return
-
EINVAL
;
return
start_ts_capture
(
budget
);
}
static
int
budget_stop_feed
(
struct
dvb_demux_feed
*
feed
)
{
struct
dvb_demux
*
demux
=
feed
->
demux
;
struct
budget
*
budget
=
(
struct
budget
*
)
demux
->
priv
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
return
stop_ts_capture
(
budget
);
}
static
int
budget_register
(
struct
budget
*
budget
)
{
int
ret
;
dmx_frontend_t
*
dvbfront
=&
budget
->
hw_frontend
;
struct
dvb_demux
*
dvbdemux
=&
budget
->
demux
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
memcpy
(
budget
->
demux_id
,
"demux0_0"
,
9
);
budget
->
demux_id
[
5
]
=
budget
->
dvb_adapter
->
num
+
'0'
;
dvbdemux
->
priv
=
(
void
*
)
budget
;
dvbdemux
->
filternum
=
256
;
dvbdemux
->
feednum
=
256
;
dvbdemux
->
start_feed
=
budget_start_feed
;
dvbdemux
->
stop_feed
=
budget_stop_feed
;
dvbdemux
->
write_to_decoder
=
NULL
;
dvbdemux
->
dmx
.
vendor
=
"CIM"
;
dvbdemux
->
dmx
.
model
=
"sw"
;
dvbdemux
->
dmx
.
id
=
budget
->
demux_id
;
dvbdemux
->
dmx
.
capabilities
=
(
DMX_TS_FILTERING
|
DMX_SECTION_FILTERING
|
DMX_MEMORY_BASED_FILTERING
);
dvb_dmx_init
(
&
budget
->
demux
);
dvbfront
->
id
=
"hw_frontend"
;
dvbfront
->
vendor
=
"VLSI"
;
dvbfront
->
model
=
"DVB Frontend"
;
dvbfront
->
source
=
DMX_FRONTEND_0
;
budget
->
dmxdev
.
filternum
=
256
;
budget
->
dmxdev
.
demux
=
&
dvbdemux
->
dmx
;
budget
->
dmxdev
.
capabilities
=
0
;
dvb_dmxdev_init
(
&
budget
->
dmxdev
,
budget
->
dvb_adapter
);
ret
=
dvbdemux
->
dmx
.
add_frontend
(
&
dvbdemux
->
dmx
,
&
budget
->
hw_frontend
);
if
(
ret
<
0
)
return
ret
;
budget
->
mem_frontend
.
id
=
"mem_frontend"
;
budget
->
mem_frontend
.
vendor
=
"memory"
;
budget
->
mem_frontend
.
model
=
"sw"
;
budget
->
mem_frontend
.
source
=
DMX_MEMORY_FE
;
ret
=
dvbdemux
->
dmx
.
add_frontend
(
&
dvbdemux
->
dmx
,
&
budget
->
mem_frontend
);
if
(
ret
<
0
)
return
ret
;
ret
=
dvbdemux
->
dmx
.
connect_frontend
(
&
dvbdemux
->
dmx
,
&
budget
->
hw_frontend
);
if
(
ret
<
0
)
return
ret
;
budget
->
dvb_net
.
card_num
=
budget
->
dvb_adapter
->
num
;
dvb_net_init
(
budget
->
dvb_adapter
,
&
budget
->
dvb_net
,
&
dvbdemux
->
dmx
);
return
0
;
}
static
void
budget_unregister
(
struct
budget
*
budget
)
{
struct
dvb_demux
*
dvbdemux
=&
budget
->
demux
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
dvb_net_release
(
&
budget
->
dvb_net
);
dvbdemux
->
dmx
.
close
(
&
dvbdemux
->
dmx
);
dvbdemux
->
dmx
.
remove_frontend
(
&
dvbdemux
->
dmx
,
&
budget
->
hw_frontend
);
dvbdemux
->
dmx
.
remove_frontend
(
&
dvbdemux
->
dmx
,
&
budget
->
mem_frontend
);
dvb_dmxdev_release
(
&
budget
->
dmxdev
);
dvb_dmx_release
(
&
budget
->
demux
);
}
static
int
master_xfer
(
struct
dvb_i2c_bus
*
i2c
,
const
struct
i2c_msg
msgs
[],
int
num
)
{
struct
saa7146_dev
*
dev
=
i2c
->
data
;
return
saa7146_i2c_transfer
(
dev
,
msgs
,
num
,
6
);
}
int
ttpci_budget_init
(
struct
budget
*
budget
,
struct
saa7146_dev
*
dev
,
struct
saa7146_pci_extension_data
*
info
)
{
int
length
=
TS_WIDTH
*
TS_HEIGHT
;
int
ret
=
0
;
struct
budget_info
*
bi
=
info
->
ext_priv
;
memset
(
budget
,
0
,
sizeof
(
struct
budget
));
DEB_EE
((
"dev: %p, budget: %p
\n
"
,
dev
,
budget
));
budget
->
card
=
bi
;
budget
->
dev
=
(
struct
saa7146_dev
*
)
dev
;
dvb_register_adapter
(
&
budget
->
dvb_adapter
,
budget
->
card
->
name
);
/* set dd1 stream a & b */
saa7146_write
(
dev
,
DD1_STREAM_B
,
0x00000000
);
saa7146_write
(
dev
,
DD1_INIT
,
0x02000000
);
saa7146_write
(
dev
,
MC2
,
(
MASK_09
|
MASK_25
|
MASK_10
|
MASK_26
));
/* the Siemens DVB needs this if you want to have the i2c chips
get recognized before the main driver is loaded */
saa7146_write
(
dev
,
GPIO_CTRL
,
0x500000
);
saa7146_i2c_adapter_prepare
(
dev
,
NULL
,
SAA7146_I2C_BUS_BIT_RATE_3200
);
budget
->
i2c_bus
=
dvb_register_i2c_bus
(
master_xfer
,
dev
,
budget
->
dvb_adapter
,
0
);
if
(
!
budget
->
i2c_bus
)
{
dvb_unregister_adapter
(
budget
->
dvb_adapter
);
return
-
ENOMEM
;
}
if
(
NULL
==
(
budget
->
grabbing
=
saa7146_vmalloc_build_pgtable
(
dev
->
pci
,
length
,
&
budget
->
pt
)))
{
ret
=
-
ENOMEM
;
goto
err
;
}
saa7146_write
(
dev
,
PCI_BT_V1
,
0x001c0000
);
/* upload all */
saa7146_write
(
dev
,
GPIO_CTRL
,
0x000000
);
tasklet_init
(
&
budget
->
vpe_tasklet
,
vpeirq
,
(
unsigned
long
)
budget
);
saa7146_setgpio
(
dev
,
2
,
SAA7146_GPIO_OUTHI
);
/* frontend power on */
if
(
budget_register
(
budget
)
==
0
)
return
0
;
err:
if
(
budget
->
grabbing
)
vfree
(
budget
->
grabbing
);
dvb_unregister_i2c_bus
(
master_xfer
,
budget
->
i2c_bus
->
adapter
,
budget
->
i2c_bus
->
id
);
dvb_unregister_adapter
(
budget
->
dvb_adapter
);
return
ret
;
}
int
ttpci_budget_deinit
(
struct
budget
*
budget
)
{
struct
saa7146_dev
*
dev
=
budget
->
dev
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
budget_unregister
(
budget
);
dvb_unregister_i2c_bus
(
master_xfer
,
budget
->
i2c_bus
->
adapter
,
budget
->
i2c_bus
->
id
);
dvb_unregister_adapter
(
budget
->
dvb_adapter
);
tasklet_kill
(
&
budget
->
vpe_tasklet
);
saa7146_pgtable_free
(
dev
->
pci
,
&
budget
->
pt
);
vfree
(
budget
->
grabbing
);
kfree
(
budget
);
return
0
;
}
void
ttpci_budget_irq10_handler
(
struct
saa7146_dev
*
dev
,
u32
*
isr
)
{
struct
budget
*
budget
=
(
struct
budget
*
)
dev
->
ext_priv
;
DEB_EE
((
"dev: %p, budget: %p
\n
"
,
dev
,
budget
));
if
(
*
isr
&
MASK_10
)
tasklet_schedule
(
&
budget
->
vpe_tasklet
);
}
EXPORT_SYMBOL_GPL
(
ttpci_budget_init
);
EXPORT_SYMBOL_GPL
(
ttpci_budget_deinit
);
EXPORT_SYMBOL_GPL
(
ttpci_budget_irq10_handler
);
EXPORT_SYMBOL_GPL
(
budget_debug
);
MODULE_PARM
(
budget_debug
,
"i"
);
MODULE_LICENSE
(
"GPL"
);
drivers/media/dvb/ttpci/budget-patch.c
0 → 100644
View file @
24824a0e
/*
* budget-patch.c: driver for Budget Patch,
* hardware modification of DVB-S cards enabling full TS
*
* Written by Emard <emard@softhome.net>
*
* Original idea by Roberto Deza <rdeza@unav.es>
*
* Special thanks to Holger Waechtler, Michael Hunold, Marian Durkovic
* and Metzlerbros
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
#include "budget.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#define KBUILD_MODNAME budget_patch
#endif
#define budget_patch budget
static
struct
saa7146_extension
budget_extension
;
MAKE_BUDGET_INFO
(
fs_1_3
,
"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch"
,
BUDGET_PATCH
);
static
struct
pci_device_id
pci_tbl
[]
=
{
MAKE_EXTENSION_PCI
(
fs_1_3
,
0x13c2
,
0x0000
),
{
.
vendor
=
0
,
}
};
#define COMMAND (DPRAM_BASE + 0x0FC)
#define DPRAM_BASE 0x4000
#define DEBINOSWAP 0x000e0000
typedef
enum
{
AudioDAC
,
CabADAC
,
ON22K
,
OFF22K
,
MainSwitch
,
ADSwitch
,
SendDiSEqC
,
SetRegister
}
AUDCOM
;
typedef
enum
{
COMTYPE_NOCOM
,
COMTYPE_PIDFILTER
,
COMTYPE_MPEGDECODER
,
COMTYPE_OSD
,
COMTYPE_BMP
,
COMTYPE_ENCODER
,
COMTYPE_AUDIODAC
,
COMTYPE_REQUEST
,
COMTYPE_SYSTEM
,
COMTYPE_REC_PLAY
,
COMTYPE_COMMON_IF
,
COMTYPE_PID_FILTER
,
COMTYPE_PES
,
COMTYPE_TS
,
COMTYPE_VIDEO
,
COMTYPE_AUDIO
,
COMTYPE_CI_LL
,
}
COMTYPE
;
static
int
wdebi
(
struct
budget_patch
*
budget
,
u32
config
,
int
addr
,
u32
val
,
int
count
)
{
struct
saa7146_dev
*
dev
=
budget
->
dev
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
(
count
<=
0
||
count
>
4
)
return
-
1
;
saa7146_write
(
dev
,
DEBI_CONFIG
,
config
);
saa7146_write
(
dev
,
DEBI_AD
,
val
);
saa7146_write
(
dev
,
DEBI_COMMAND
,
(
count
<<
17
)
|
(
addr
&
0xffff
));
saa7146_write
(
dev
,
MC2
,
(
2
<<
16
)
|
2
);
mdelay
(
5
);
return
0
;
}
static
int
SOutCommand
(
struct
budget_patch
*
budget
,
u16
*
buf
,
int
length
)
{
int
i
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
for
(
i
=
2
;
i
<
length
;
i
++
)
wdebi
(
budget
,
DEBINOSWAP
,
COMMAND
+
2
*
i
,
(
u32
)
buf
[
i
],
2
);
if
(
length
)
wdebi
(
budget
,
DEBINOSWAP
,
COMMAND
+
2
,
(
u32
)
buf
[
1
],
2
);
else
wdebi
(
budget
,
DEBINOSWAP
,
COMMAND
+
2
,
0
,
2
);
wdebi
(
budget
,
DEBINOSWAP
,
COMMAND
,
(
u32
)
buf
[
0
],
2
);
return
0
;
}
static
void
av7110_set22k
(
struct
budget_patch
*
budget
,
int
state
)
{
u16
buf
[
2
]
=
{(
COMTYPE_AUDIODAC
<<
8
)
|
(
state
?
ON22K
:
OFF22K
),
0
};
DEB_EE
((
"budget: %p
\n
"
,
budget
));
SOutCommand
(
budget
,
buf
,
2
);
}
static
int
av7110_send_diseqc_msg
(
struct
budget_patch
*
budget
,
int
len
,
u8
*
msg
,
int
burst
)
{
int
i
;
u16
buf
[
18
]
=
{
((
COMTYPE_AUDIODAC
<<
8
)
|
SendDiSEqC
),
16
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
};
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
(
len
>
10
)
len
=
10
;
buf
[
1
]
=
len
+
2
;
buf
[
2
]
=
len
;
if
(
burst
!=
-
1
)
buf
[
3
]
=
burst
?
0x01
:
0x00
;
else
buf
[
3
]
=
0xffff
;
for
(
i
=
0
;
i
<
len
;
i
++
)
buf
[
i
+
4
]
=
msg
[
i
];
SOutCommand
(
budget
,
buf
,
18
);
return
0
;
}
int
budget_patch_diseqc_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
struct
budget_patch
*
budget
=
fe
->
before_after_data
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
switch
(
cmd
)
{
case
FE_SET_TONE
:
switch
((
fe_sec_tone_mode_t
)
arg
)
{
case
SEC_TONE_ON
:
av7110_set22k
(
budget
,
1
);
break
;
case
SEC_TONE_OFF
:
av7110_set22k
(
budget
,
0
);
break
;
default:
return
-
EINVAL
;
}
break
;
case
FE_DISEQC_SEND_MASTER_CMD
:
{
struct
dvb_diseqc_master_cmd
*
cmd
=
arg
;
av7110_send_diseqc_msg
(
budget
,
cmd
->
msg_len
,
cmd
->
msg
,
0
);
break
;
}
case
FE_DISEQC_SEND_BURST
:
av7110_send_diseqc_msg
(
budget
,
0
,
NULL
,
(
int
)
arg
);
break
;
default:
return
-
EOPNOTSUPP
;
}
return
0
;
}
static
int
budget_patch_attach
(
struct
saa7146_dev
*
dev
,
struct
saa7146_pci_extension_data
*
info
)
{
struct
budget_patch
*
budget
;
int
err
;
int
cnt
;
if
(
!
(
budget
=
kmalloc
(
sizeof
(
struct
budget_patch
),
GFP_KERNEL
)))
return
-
ENOMEM
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
((
err
=
ttpci_budget_init
(
budget
,
dev
,
info
)))
{
kfree
(
budget
);
return
err
;
}
/*
** This code will setup the SAA7146_RPS1 to generate a square
** wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of
** TS_WIDTH packets) has been acquired on SAA7146_D1B video port;
** then, this GPIO3 output which is connected to the D1B_VSYNC
** input, will trigger the acquisition of the alternate field
** and so on.
** Currently, the TT_budget / WinTV_Nova cards have two ICs
** (74HCT4040, LVC74) for the generation of this VSYNC signal,
** which seems that can be done perfectly without this :-)).
*/
cnt
=
0
;
// Setup RPS1 "program" (p35)
// Wait reset Source Line Counter Threshold (p36)
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_PAUSE
|
RPS_INV
|
EVT_HS
);
// Wait Source Line Counter Threshold (p36)
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_PAUSE
|
EVT_HS
);
// Set GPIO3=1 (p42)
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_WR_REG_MASK
|
(
GPIO_CTRL
>>
2
));
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
GPIO3_MSK
);
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
SAA7146_GPIO_OUTHI
<<
24
);
// Wait reset Source Line Counter Threshold (p36)
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_PAUSE
|
RPS_INV
|
EVT_HS
);
// Wait Source Line Counter Threshold
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_PAUSE
|
EVT_HS
);
// Set GPIO3=0 (p42)
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_WR_REG_MASK
|
(
GPIO_CTRL
>>
2
));
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
GPIO3_MSK
);
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
SAA7146_GPIO_OUTLO
<<
24
);
// Jump to begin of RPS program (p37)
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
CMD_JUMP
);
dev
->
rps1
[
cnt
++
]
=
cpu_to_le32
(
virt_to_bus
(
&
dev
->
rps1
[
0
]));
// Fix VSYNC level
saa7146_setgpio
(
dev
,
3
,
SAA7146_GPIO_OUTLO
);
// Set RPS1 Address register to point to RPS code (r108 p42)
saa7146_write
(
dev
,
RPS_ADDR1
,
virt_to_bus
(
&
dev
->
rps1
[
0
]));
// Set Source Line Counter Threshold, using BRS (rCC p43)
saa7146_write
(
dev
,
RPS_THRESH1
,
((
TS_HEIGHT
/
2
)
|
MASK_12
));
// Enable RPS1 (rFC p33)
saa7146_write
(
dev
,
MC1
,
(
MASK_13
|
MASK_29
));
dvb_add_frontend_ioctls
(
budget
->
dvb_adapter
,
budget_patch_diseqc_ioctl
,
NULL
,
budget
);
dev
->
ext_priv
=
budget
;
return
0
;
}
static
int
budget_patch_detach
(
struct
saa7146_dev
*
dev
)
{
struct
budget_patch
*
budget
=
(
struct
budget_patch
*
)
dev
->
ext_priv
;
int
err
;
dvb_remove_frontend_ioctls
(
budget
->
dvb_adapter
,
budget_patch_diseqc_ioctl
,
NULL
);
err
=
ttpci_budget_deinit
(
budget
);
kfree
(
budget
);
return
err
;
}
static
int
__init
budget_patch_init
(
void
)
{
if
(
saa7146_register_extension
(
&
budget_extension
))
return
-
ENODEV
;
return
0
;
}
static
void
__exit
budget_patch_exit
(
void
)
{
DEB_EE
((
".
\n
"
));
saa7146_unregister_extension
(
&
budget_extension
);
}
static
struct
saa7146_extension
budget_extension
=
{
.
name
=
"budget_patch dvb
\0
"
,
.
flags
=
0
,
.
ext_vv_data
=
NULL
,
.
module
=
THIS_MODULE
,
.
pci_tbl
=
pci_tbl
,
.
attach
=
budget_patch_attach
,
.
detach
=
budget_patch_detach
,
.
irq_mask
=
MASK_10
,
.
irq_func
=
ttpci_budget_irq10_handler
,
};
module_init
(
budget_patch_init
);
module_exit
(
budget_patch_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others"
);
MODULE_DESCRIPTION
(
"Driver for full TS modified DVB-S SAA7146+AV7110 "
"based so-called Budget Patch cards"
);
drivers/media/dvb/ttpci/budget.c
0 → 100644
View file @
24824a0e
/*
* budget.c: driver for the SAA7146 based Budget DVB cards
*
* Compiled from various sources by Michael Hunold <michael@mihu.de>
*
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
*
* Copyright (C) 1999-2002 Ralph Metzler
* & Marcus Metzler for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*
*
* the project's page is at http://www.linuxtv.org/dvb/
*/
#include "budget.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51)
#define KBUILD_MODNAME budget
#endif
static
inline
void
ddelay
(
int
i
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
((
HZ
*
i
)
/
100
);
}
static
void
Set22K
(
struct
budget
*
budget
,
int
state
)
{
struct
saa7146_dev
*
dev
=
budget
->
dev
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
saa7146_setgpio
(
dev
,
3
,
(
state
?
SAA7146_GPIO_OUTHI
:
SAA7146_GPIO_OUTLO
));
}
/* Diseqc functions only for TT Budget card */
/* taken from the Skyvision DVB driver by
Ralph Metzler <rjkm@metzlerbros.de> */
static
void
DiseqcSendBit
(
struct
budget
*
budget
,
int
data
)
{
struct
saa7146_dev
*
dev
=
budget
->
dev
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
saa7146_setgpio
(
dev
,
3
,
SAA7146_GPIO_OUTHI
);
udelay
(
data
?
500
:
1000
);
saa7146_setgpio
(
dev
,
3
,
SAA7146_GPIO_OUTLO
);
udelay
(
data
?
1000
:
500
);
}
static
void
DiseqcSendByte
(
struct
budget
*
budget
,
int
data
)
{
int
i
,
par
=
1
,
d
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
for
(
i
=
7
;
i
>=
0
;
i
--
)
{
d
=
(
data
>>
i
)
&
1
;
par
^=
d
;
DiseqcSendBit
(
budget
,
d
);
}
DiseqcSendBit
(
budget
,
par
);
}
static
int
SendDiSEqCMsg
(
struct
budget
*
budget
,
int
len
,
u8
*
msg
,
int
burst
)
{
struct
saa7146_dev
*
dev
=
budget
->
dev
;
int
i
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
saa7146_setgpio
(
dev
,
3
,
SAA7146_GPIO_OUTLO
);
mdelay
(
16
);
for
(
i
=
0
;
i
<
len
;
i
++
)
DiseqcSendByte
(
budget
,
msg
[
i
]);
mdelay
(
16
);
if
(
burst
!=-
1
)
{
if
(
burst
)
DiseqcSendByte
(
budget
,
0xff
);
else
{
saa7146_setgpio
(
dev
,
3
,
SAA7146_GPIO_OUTHI
);
udelay
(
12500
);
saa7146_setgpio
(
dev
,
3
,
SAA7146_GPIO_OUTLO
);
}
ddelay
(
2
);
}
return
0
;
}
int
budget_diseqc_ioctl
(
struct
dvb_frontend
*
fe
,
unsigned
int
cmd
,
void
*
arg
)
{
struct
budget
*
budget
=
fe
->
before_after_data
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
switch
(
cmd
)
{
case
FE_SET_TONE
:
switch
((
fe_sec_tone_mode_t
)
arg
)
{
case
SEC_TONE_ON
:
Set22K
(
budget
,
1
);
break
;
case
SEC_TONE_OFF
:
Set22K
(
budget
,
0
);
break
;
default:
return
-
EINVAL
;
};
break
;
case
FE_DISEQC_SEND_MASTER_CMD
:
{
struct
dvb_diseqc_master_cmd
*
cmd
=
arg
;
SendDiSEqCMsg
(
budget
,
cmd
->
msg_len
,
cmd
->
msg
,
0
);
break
;
}
case
FE_DISEQC_SEND_BURST
:
SendDiSEqCMsg
(
budget
,
0
,
NULL
,
(
int
)
arg
);
break
;
default:
return
-
EOPNOTSUPP
;
};
return
0
;
}
static
int
budget_attach
(
struct
saa7146_dev
*
dev
,
struct
saa7146_pci_extension_data
*
info
)
{
struct
budget
*
budget
;
int
err
;
if
(
!
(
budget
=
kmalloc
(
sizeof
(
struct
budget
),
GFP_KERNEL
)))
return
-
ENOMEM
;
DEB_EE
((
"budget: %p
\n
"
,
budget
));
if
((
err
=
ttpci_budget_init
(
budget
,
dev
,
info
)))
{
kfree
(
budget
);
return
err
;
}
dvb_add_frontend_ioctls
(
budget
->
dvb_adapter
,
budget_diseqc_ioctl
,
NULL
,
budget
);
dev
->
ext_priv
=
budget
;
return
0
;
}
static
int
budget_detach
(
struct
saa7146_dev
*
dev
)
{
struct
budget
*
budget
=
(
struct
budget
*
)
dev
->
ext_priv
;
int
err
;
dvb_remove_frontend_ioctls
(
budget
->
dvb_adapter
,
budget_diseqc_ioctl
,
NULL
);
err
=
ttpci_budget_deinit
(
budget
);
kfree
(
budget
);
return
err
;
}
static
struct
saa7146_extension
budget_extension
;
MAKE_BUDGET_INFO
(
ttbs
,
"TT-Budget/WinTV-NOVA-S PCI"
,
BUDGET_TT
);
MAKE_BUDGET_INFO
(
ttbc
,
"TT-Budget/WinTV-NOVA-C PCI"
,
BUDGET_TT
);
MAKE_BUDGET_INFO
(
ttbt
,
"TT-Budget/WinTV-NOVA-T PCI"
,
BUDGET_TT
);
MAKE_BUDGET_INFO
(
satel
,
"SATELCO Multimedia PCI"
,
BUDGET_TT_HW_DISEQC
);
/* Uncomment for Budget Patch */
/*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/
static
struct
pci_device_id
pci_tbl
[]
=
{
/* Uncomment for Budget Patch */
/*MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000),*/
MAKE_EXTENSION_PCI
(
ttbs
,
0x13c2
,
0x1003
),
MAKE_EXTENSION_PCI
(
ttbc
,
0x13c2
,
0x1004
),
MAKE_EXTENSION_PCI
(
ttbt
,
0x13c2
,
0x1005
),
MAKE_EXTENSION_PCI
(
satel
,
0x13c2
,
0x1013
),
{
.
vendor
=
0
,
}
};
static
struct
saa7146_extension
budget_extension
=
{
.
name
=
"budget dvb
\0
"
,
.
flags
=
0
,
.
ext_vv_data
=
NULL
,
.
module
=
THIS_MODULE
,
.
pci_tbl
=
pci_tbl
,
.
attach
=
budget_attach
,
.
detach
=
budget_detach
,
.
irq_mask
=
MASK_10
,
.
irq_func
=
ttpci_budget_irq10_handler
,
};
static
int
__init
budget_init
(
void
)
{
if
(
saa7146_register_extension
(
&
budget_extension
))
return
-
ENODEV
;
return
0
;
}
static
void
__exit
budget_exit
(
void
)
{
DEB_EE
((
".
\n
"
));
saa7146_unregister_extension
(
&
budget_extension
);
}
module_init
(
budget_init
);
module_exit
(
budget_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Ralph Metzler, Marcus Metzler, Michael Hunold, others"
);
MODULE_DESCRIPTION
(
"driver for the SAA7146 based so-called "
"budget PCI DVB cards by Siemens, Technotrend, Hauppauge"
);
drivers/media/dvb/ttpci/budget.h
0 → 100644
View file @
24824a0e
#ifndef __BUDGET_DVB__
#define __BUDGET_DVB__
#include "dvb_i2c.h"
#include "dvb_frontend.h"
#include "dvbdev.h"
#include "demux.h"
#include "dvb_demux.h"
#include "dmxdev.h"
#include "dvb_filter.h"
#include "dvb_net.h"
#include <media/saa7146.h>
extern
int
budget_debug
;
struct
budget_info
{
char
*
name
;
int
type
;
};
/* place to store all the necessary device information */
struct
budget
{
/* devices */
struct
dvb_device
dvb_dev
;
dvb_net_t
dvb_net
;
struct
saa7146_dev
*
dev
;
struct
dvb_i2c_bus
*
i2c_bus
;
struct
budget_info
*
card
;
unsigned
char
*
grabbing
;
struct
saa7146_pgtable
pt
;
struct
tasklet_struct
fidb_tasklet
;
struct
tasklet_struct
vpe_tasklet
;
dmxdev_t
dmxdev
;
struct
dvb_demux
demux
;
char
demux_id
[
16
];
dmx_frontend_t
hw_frontend
;
dmx_frontend_t
mem_frontend
;
int
fe_synced
;
struct
semaphore
pid_mutex
;
u8
tsf
;
u32
ttbp
;
int
feeding
;
struct
dvb_adapter
*
dvb_adapter
;
void
*
priv
;
};
#define MAKE_BUDGET_INFO(x_var,x_name,x_type) \
static struct budget_info x_var ## _info = { \
.name=x_name, \
.type=x_type }; \
static struct saa7146_pci_extension_data x_var = { \
.ext_priv = &x_var ## _info, \
.ext = &budget_extension };
#define TS_WIDTH (4*188)
#define TS_HEIGHT (1024/4)
#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
#define BUDGET_TT 0
#define BUDGET_TT_HW_DISEQC 1
#define BUDGET_KNC1 2
#define BUDGET_PATCH 3
extern
int
ttpci_budget_init
(
struct
budget
*
budget
,
struct
saa7146_dev
*
dev
,
struct
saa7146_pci_extension_data
*
info
);
extern
int
ttpci_budget_deinit
(
struct
budget
*
budget
);
extern
void
ttpci_budget_irq10_handler
(
struct
saa7146_dev
*
dev
,
u32
*
isr
);
#endif
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