Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
de3fe21b
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,发现更多精彩内容 >>
提交
de3fe21b
编写于
10月 24, 2007
作者:
M
Mauro Carvalho Chehab
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
V4L/DVB (6431): Improve firmware format
Signed-off-by:
N
Mauro Carvalho Chehab
<
mchehab@infradead.org
>
上级
215b95ba
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
455 addition
and
111 deletion
+455
-111
drivers/media/video/tuner-xc2028-types.h
drivers/media/video/tuner-xc2028-types.h
+99
-0
drivers/media/video/tuner-xc2028.c
drivers/media/video/tuner-xc2028.c
+344
-108
drivers/media/video/tuner-xc2028.h
drivers/media/video/tuner-xc2028.h
+12
-3
未找到文件。
drivers/media/video/tuner-xc2028-types.h
0 → 100644
浏览文件 @
de3fe21b
/* tuner-xc2028_types
*
* Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org)
* This code is placed under the terms of the GNU General Public License v2
*/
/* xc3028 firmware types */
/* BASE firmware should be loaded before any other firmware */
#define BASE (1<<0)
/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
#define F8MHZ (1<<1)
/* Multichannel Television Sound (MTS)
Those firmwares are capable of using xc2038 DSP to decode audio and
produce a baseband audio output on some pins of the chip.
There are MTS firmwares for the most used video standards. It should be
required to use MTS firmwares, depending on the way audio is routed into
the bridge chip
*/
#define MTS (1<<2)
/* FIXME: I have no idea what's the difference between
D2620 and D2633 firmwares
*/
#define D2620 (1<<3)
#define D2633 (1<<4)
/* DTV firmwares for 6, 7 and 8 MHz
DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS
DTV8 - 8MHz - DVB-C/DVB-T
*/
#define DTV6_ATSC (1<<5)
#define DTV6_QAM (1<<6)
#define DTV7 (1<<7)
#define DTV78 (1<<8)
#define DTV8 (1<<9)
/* There's a FM | BASE firmware + FM specific firmware (std=0) */
#define FM (1<<10)
/* Applies only for FM firmware
Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
*/
#define INPUT1 (1<<11)
/* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
There are variants both with and without NOGD
*/
#define LCD (1<<12)
/* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
*/
#define NOGD (1<<13)
/* Old firmwares were broken into init0 and init1 */
#define INIT1 (1<<14)
/* Newer types to be moved to videodev2.h */
#define V4L2_STD_SECAM_K3 (0x02000000)
/* Audio types */
#define V4L2_STD_A2_A (1L<<32)
#define V4L2_STD_A2_B (1L<<33)
#define V4L2_STD_NICAM_A (1L<<34)
#define V4L2_STD_NICAM_B (1L<<35)
#define V4L2_STD_AM (1L<<36)
#define V4L2_STD_BTSC (1L<<37)
#define V4L2_STD__EIAJ (1L<<38)
#define V4L2_STD_A2 (V4L2_STD_A2_A | V4L2_STD_A2_B)
#define V4L2_STD_NICAM (V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
/* To preserve backward compatibilty,
(std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
*/
#define V4L2_STD_AUDIO (V4L2_STD_A2 | \
V4L2_STD_NICAM | \
V4L2_STD_AM | \
V4L2_STD_BTSC | \
V4L2_STD_EIAJ)
/* Used standards with audio restrictions */
#define V4L2_STD_PAL_BG_A2_A (V4L2_STD_PAL_BG | V4L2_STD_A2_A)
#define V4L2_STD_PAL_BG_A2_B (V4L2_STD_PAL_BG | V4L2_STD_A2_B)
#define V4L2_STD_PAL_BG_NICAM_A (V4L2_STD_PAL_BG | V4L2_STD_NICAM_A)
#define V4L2_STD_PAL_BG_NICAM_B (V4L2_STD_PAL_BG | V4L2_STD_NICAM_B)
#define V4L2_STD_PAL_DK_A2 (V4L2_STD_PAL_DK | V4L2_STD_A2)
#define V4L2_STD_PAL_DK_NICAM (V4L2_STD_PAL_DK | V4L2_STD_NICAM)
#define V4L2_STD_SECAM_L_NICAM (V4L2_STD_SECAM_L | V4L2_STD_NICAM)
#define V4L2_STD_SECAM_L_AM (V4L2_STD_SECAM_L | V4L2_STD_AM)
drivers/media/video/tuner-xc2028.c
浏览文件 @
de3fe21b
...
...
@@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include "tuner-i2c.h"
#include "tuner-xc2028.h"
#include "tuner-xc2028-types.h"
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
...
...
@@ -22,21 +23,13 @@
#define PREFIX "xc2028 "
static
LIST_HEAD
(
xc2028_list
);
/* Firmwares used on tm5600/tm6000 + xc2028/xc3028 */
/* Generic firmwares */
static
const
char
*
firmware_INIT0
=
"tm_xc3028_MTS_init0.fw"
;
static
const
char
*
firmware_8MHZ_INIT0
=
"tm_xc3028_8M_MTS_init0.fw"
;
static
const
char
*
firmware_INIT1
=
"tm_xc3028_68M_MTS_init1.fw"
;
/* Standard-specific firmwares */
static
const
char
*
firmware_6M
=
"tm_xc3028_DTV_6M.fw"
;
static
const
char
*
firmware_7M
=
"tm_xc3028_DTV_7M.fw"
;
static
const
char
*
firmware_8M
=
"tm_xc3028_DTV_8M.fw"
;
static
const
char
*
firmware_B
=
"tm_xc3028_B_PAL.fw"
;
static
const
char
*
firmware_DK
=
"tm_xc3028_DK_PAL_MTS.fw"
;
static
const
char
*
firmware_MN
=
"tm_xc3028_MN_BTSC.fw"
;
/* struct for storing firmware table */
struct
firmware_description
{
unsigned
int
type
;
v4l2_std_id
id
;
unsigned
char
*
ptr
;
unsigned
int
size
;
};
struct
xc2028_data
{
struct
list_head
xc2028_list
;
...
...
@@ -46,7 +39,14 @@ struct xc2028_data {
struct
device
*
dev
;
void
*
video_dev
;
int
count
;
u32
frequency
;
__u32
frequency
;
struct
firmware_description
*
firm
;
int
firm_size
;
__u16
version
;
struct
xc2028_ctrl
ctrl
;
v4l2_std_id
firm_type
;
/* video stds supported
by current firmware */
...
...
@@ -54,6 +54,9 @@ struct xc2028_data {
6M, 7M or 8M */
int
need_load_generic
;
/* The generic firmware
were loaded? */
int
max_len
;
/* Max firmware chunk */
enum
tuner_mode
mode
;
struct
i2c_client
*
i2c_client
;
...
...
@@ -102,92 +105,263 @@ static int xc2028_get_reg(struct xc2028_data *priv, u16 reg)
return
(
buf
[
1
])
|
(
buf
[
0
]
<<
8
);
}
static
int
load_firmware
(
struct
dvb_frontend
*
fe
,
const
char
*
name
)
static
void
free_firmware
(
struct
xc2028_data
*
priv
)
{
struct
xc2028_data
*
priv
=
fe
->
tuner_priv
;
int
i
;
if
(
!
priv
->
firm
)
return
;
for
(
i
=
0
;
i
<
priv
->
firm_size
;
i
++
)
{
if
(
priv
->
firm
[
i
].
ptr
)
kfree
(
priv
->
firm
[
i
].
ptr
);
}
kfree
(
priv
->
firm
);
priv
->
firm
=
NULL
;
priv
->
need_load_generic
=
1
;
}
static
int
load_all_firmwares
(
struct
dvb_frontend
*
fe
)
{
struct
xc2028_data
*
priv
=
fe
->
tuner_priv
;
const
struct
firmware
*
fw
=
NULL
;
unsigned
char
*
p
,
*
endp
;
int
len
=
0
,
rc
=
0
;
static
const
char
firmware_ver
[]
=
"tm6000/xcv v1"
;
int
rc
=
0
,
n
,
n_array
;
char
name
[
33
]
;
tuner_info
(
"%s called
\n
"
,
__FUNCTION__
);
tuner_info
(
"Loading firmware %s
\n
"
,
name
);
rc
=
request_firmware
(
&
fw
,
name
,
priv
->
dev
);
tuner_info
(
"Loading firmware %s
\n
"
,
priv
->
ctrl
.
f
name
);
rc
=
request_firmware
(
&
fw
,
priv
->
ctrl
.
f
name
,
priv
->
dev
);
if
(
rc
<
0
)
{
if
(
rc
==-
ENOENT
)
tuner_info
(
"Error: firmware %s not found.
\n
"
,
name
);
tuner_info
(
"Error: firmware %s not found.
\n
"
,
priv
->
ctrl
.
fname
);
else
tuner_info
(
"Error %d while requesting firmware %s
\n
"
,
rc
,
name
);
tuner_info
(
"Error %d while requesting firmware %s
\n
"
,
rc
,
priv
->
ctrl
.
fname
);
return
rc
;
}
p
=
fw
->
data
;
endp
=
p
+
fw
->
size
;
if
(
fw
->
size
==
0
)
{
if
(
fw
->
size
<
sizeof
(
name
)
-
1
+
2
)
{
tuner_info
(
"Error: firmware size is zero!
\n
"
);
rc
=-
EINVAL
;
goto
err
;
goto
done
;
}
if
(
fw
->
size
<
sizeof
(
firmware_ver
)
-
1
)
{
/* Firmware is incorrect */
tuner_info
(
"Error: firmware size is less than header (%d<%d)!
\n
"
,
(
int
)
fw
->
size
,(
int
)
sizeof
(
firmware_ver
)
-
1
);
rc
=-
EINVAL
;
goto
err
;
memcpy
(
name
,
p
,
sizeof
(
name
)
-
1
);
name
[
sizeof
(
name
)
-
1
]
=
0
;
p
+=
sizeof
(
name
)
-
1
;
priv
->
version
=
le16_to_cpu
(
*
(
__u16
*
)
p
);
p
+=
2
;
tuner_info
(
"firmware: %s, ver %d.%d
\n
"
,
name
,
priv
->
version
>>
8
,
priv
->
version
&
0xff
);
if
(
p
+
2
>
endp
)
goto
corrupt
;
n_array
=
le16_to_cpu
(
*
(
__u16
*
)
p
);
p
+=
2
;
tuner_info
(
"there are %d firmwares at %s
\n
"
,
n_array
,
priv
->
ctrl
.
fname
);
priv
->
firm
=
kzalloc
(
sizeof
(
*
priv
->
firm
)
*
n_array
,
GFP_KERNEL
);
if
(
!
fw
)
{
tuner_info
(
"Not enough memory for loading firmware.
\n
"
);
rc
=-
ENOMEM
;
goto
done
;
}
if
(
memcmp
(
p
,
firmware_ver
,
sizeof
(
firmware_ver
)
-
1
))
{
/* Firmware is incorrect */
tuner_info
(
"Error: firmware is not for tm5600/6000 + Xcv2028/3028!
\n
"
);
rc
=-
EINVAL
;
goto
err
;
priv
->
firm_size
=
n_array
;
n
=-
1
;
while
(
p
<
endp
)
{
__u32
type
,
size
;
v4l2_std_id
id
;
n
++
;
if
(
n
>=
n_array
)
{
tuner_info
(
"Too much firmwares at the file
\n
"
);
goto
corrupt
;
}
/* Checks if there's enough bytes to read */
if
(
p
+
sizeof
(
type
)
+
sizeof
(
id
)
+
sizeof
(
size
)
>
endp
)
{
tuner_info
(
"Lost firmware!
\n
"
);
goto
corrupt
;
}
type
=
le32_to_cpu
(
*
(
__u32
*
)
p
);
p
+=
sizeof
(
type
);
id
=
le64_to_cpu
(
*
(
v4l2_std_id
*
)
p
);
p
+=
sizeof
(
id
);
size
=
le32_to_cpu
(
*
(
v4l2_std_id
*
)
p
);
p
+=
sizeof
(
size
);
if
((
!
size
)
||
(
size
+
p
>
endp
))
{
tuner_info
(
"Firmware type %x, id %lx corrupt
\n
"
,
type
,
(
unsigned
long
)
id
);
goto
corrupt
;
}
priv
->
firm
[
n
].
ptr
=
kzalloc
(
size
,
GFP_KERNEL
);
if
(
!
priv
->
firm
[
n
].
ptr
)
{
tuner_info
(
"Not enough memory.
\n
"
);
rc
=-
ENOMEM
;
goto
err
;
}
tuner_info
(
"Loading firmware type %x, id %lx, size=%d.
\n
"
,
type
,
(
unsigned
long
)
id
,
size
);
memcpy
(
priv
->
firm
[
n
].
ptr
,
p
,
size
);
priv
->
firm
[
n
].
type
=
type
;
priv
->
firm
[
n
].
id
=
id
;
priv
->
firm
[
n
].
size
=
size
;
p
+=
size
;
}
if
(
n
+
1
!=
priv
->
firm_size
)
{
tuner_info
(
"Firmware file is incomplete!
\n
"
);
goto
corrupt
;
}
goto
done
;
corrupt:
rc
=-
EINVAL
;
tuner_info
(
"Error: firmware file is corrupted!
\n
"
);
err:
tuner_info
(
"Releasing loaded firmware file.
\n
"
);
free_firmware
(
priv
);
done:
release_firmware
(
fw
);
tuner_info
(
"Firmware files loaded.
\n
"
);
return
rc
;
}
static
int
load_firmware
(
struct
dvb_frontend
*
fe
,
unsigned
int
type
,
v4l2_std_id
*
id
)
{
struct
xc2028_data
*
priv
=
fe
->
tuner_priv
;
int
i
,
rc
;
unsigned
char
*
p
,
*
endp
,
buf
[
priv
->
max_len
];
tuner_info
(
"%s called
\n
"
,
__FUNCTION__
);
if
(
!
priv
->
firm
)
{
printk
(
KERN_ERR
PREFIX
"Error! firmware not loaded
\n
"
);
return
-
EINVAL
;
}
if
((
type
==
0
)
&&
(
*
id
==
0
))
*
id
=
V4L2_STD_PAL
;
/* Seek for exact match */
for
(
i
=
0
;
i
<
priv
->
firm_size
;
i
++
)
{
if
(
(
type
==
priv
->
firm
[
i
].
type
)
&&
(
*
id
==
priv
->
firm
[
i
].
id
))
goto
found
;
}
/* Seek for generic video standard match */
for
(
i
=
0
;
i
<
priv
->
firm_size
;
i
++
)
{
if
(
(
type
==
priv
->
firm
[
i
].
type
)
&&
(
*
id
&
priv
->
firm
[
i
].
id
))
goto
found
;
}
/*FIXME: Would make sense to seek for type "hint" match ? */
tuner_info
(
"Can't find firmware for type=%x, id=%lx
\n
"
,
type
,
(
long
int
)
*
id
);
return
-
EINVAL
;
found:
*
id
=
priv
->
firm
[
i
].
id
;
tuner_info
(
"Found firmware for type=%x, id=%lx
\n
"
,
type
,
(
long
int
)
*
id
);
p
=
priv
->
firm
[
i
].
ptr
;
if
(
!
p
)
{
printk
(
KERN_ERR
PREFIX
"Firmware pointer were freed!"
);
return
-
EINVAL
;
}
p
+=
sizeof
(
firmware_ver
)
-
1
;
endp
=
p
+
priv
->
firm
[
i
].
size
;
while
(
p
<
endp
)
{
if
((
*
p
)
&
0x80
)
{
while
(
p
<
endp
)
{
__u16
size
;
/* Checks if there's enough bytes to read */
if
(
p
+
sizeof
(
size
)
>
endp
)
{
tuner_info
(
"missing bytes
\n
"
);
return
-
EINVAL
;
}
size
=
le16_to_cpu
(
*
(
__u16
*
)
p
);
p
+=
sizeof
(
size
);
if
(
size
==
0xffff
)
return
0
;
if
(
!
size
)
{
/* Special callback command received */
rc
=
priv
->
tuner_callback
(
priv
->
video_dev
,
XC2028_TUNER_RESET
,
(
*
p
)
&
0x7f
);
XC2028_TUNER_RESET
,
0
);
if
(
rc
<
0
)
{
tuner_info
(
"Error at RESET code %d
\n
"
,
(
*
p
)
&
0x7f
);
goto
err
;
return
-
EINVAL
;
}
p
++
;
continue
;
}
len
=*
p
;
p
++
;
if
(
p
+
len
+
1
>
endp
)
{
/* Firmware is incorrect */
tuner_info
(
"Error: firmware is truncated!
\n
"
);
rc
=-
EINVAL
;
goto
err
;
}
if
(
len
<=
0
)
{
tuner_info
(
"Error: firmware file is corrupted!
\n
"
);
rc
=-
EINVAL
;
goto
err
;
/* Checks for a sleep command */
if
(
size
&
0x8000
)
{
msleep
(
size
&
0x7fff
);
continue
;
}
i2c_send
(
rc
,
priv
,
p
,
len
);
if
(
rc
<
0
)
goto
err
;
p
+=
len
;
if
((
size
+
p
>
endp
))
{
tuner_info
(
"missing bytes: need %d, have %d
\n
"
,
size
,
(
int
)(
endp
-
p
));
return
-
EINVAL
;
}
if
(
*
p
)
msleep
(
*
p
);
buf
[
0
]
=
*
p
;
p
++
;
}
size
--
;
/* Sends message chunks */
while
(
size
>
0
)
{
int
len
=
(
size
<
priv
->
max_len
-
1
)
?
size
:
priv
->
max_len
-
1
;
err:
release_firmware
(
fw
);
memcpy
(
buf
+
1
,
p
,
len
);
return
rc
;
i2c_send
(
rc
,
priv
,
buf
,
len
+
1
);
if
(
rc
<
0
)
{
tuner_info
(
"%d returned from send
\n
"
,
rc
);
return
-
EINVAL
;
}
p
+=
len
;
size
-=
len
;
}
}
return
-
EINVAL
;
}
static
int
check_firmware
(
struct
dvb_frontend
*
fe
,
enum
tuner_mode
new_mode
,
...
...
@@ -196,11 +370,21 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
{
struct
xc2028_data
*
priv
=
fe
->
tuner_priv
;
int
rc
,
version
;
const
char
*
name
;
int
change_digital_bandwidth
;
v4l2_std_id
std0
=
0
;
unsigned
int
type0
=
0
,
type
=
0
;
int
change_digital_bandwidth
;
tuner_info
(
"%s called
\n
"
,
__FUNCTION__
);
if
(
!
priv
->
firm
)
{
if
(
!
priv
->
ctrl
.
fname
)
return
-
EINVAL
;
rc
=
load_all_firmwares
(
fe
);
if
(
rc
<
0
)
return
rc
;
}
tuner_info
(
"I am in mode %u and I should switch to mode %i
\n
"
,
priv
->
mode
,
new_mode
);
...
...
@@ -213,23 +397,31 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
change_digital_bandwidth
=
(
priv
->
mode
==
T_DIGITAL_TV
&&
bandwidth
!=
priv
->
bandwidth
)
?
1
:
0
;
tuner_info
(
"old bandwidth %u, new bandwidth %u
\n
"
,
priv
->
bandwidth
,
bandwidth
);
bandwidth
);
if
(
priv
->
need_load_generic
)
{
if
(
priv
->
bandwidth
==
8
)
name
=
firmware_8MHZ_INIT0
;
else
name
=
firmware_INIT0
;
/* Reset is needed before loading firmware */
rc
=
priv
->
tuner_callback
(
priv
->
video_dev
,
XC2028_TUNER_RESET
,
0
);
if
(
rc
<
0
)
return
rc
;
rc
=
load_firmware
(
fe
,
name
);
if
(
rc
<
0
)
type0
=
BASE
;
if
(
priv
->
ctrl
.
type
==
XC2028_FIRM_MTS
)
type0
|=
MTS
;
if
(
priv
->
bandwidth
==
8
)
type0
|=
F8MHZ
;
/* FIXME: How to load FM and FM|INPUT1 firmwares? */
rc
=
load_firmware
(
fe
,
type0
,
&
std0
);
if
(
rc
<
0
)
{
tuner_info
(
"Error %d while loading generic firmware
\n
"
,
rc
);
return
rc
;
}
priv
->
need_load_generic
=
0
;
priv
->
firm_type
=
0
;
...
...
@@ -241,49 +433,53 @@ static int check_firmware(struct dvb_frontend *fe, enum tuner_mode new_mode,
tuner_info
(
"I should change bandwidth %u
\n
"
,
change_digital_bandwidth
);
/* FIXME: t->std makes no sense here */
if
(
change_digital_bandwidth
)
{
/*FIXME: Should allow selecting between D2620 and D2633 */
type
|=
D2620
;
/* FIXME: When should select a DTV78 firmware?
*/
switch
(
bandwidth
)
{
case
BANDWIDTH_8_MHZ
:
std
=
V4L2_STD_DTV_8MHZ
;
case
BANDWIDTH_8_MHZ
:
type
|=
DTV8
;
break
;
case
BANDWIDTH_7_MHZ
:
std
=
V4L2_STD_DTV_7MHZ
;
case
BANDWIDTH_7_MHZ
:
type
|=
DTV7
;
break
;
case
BANDWIDTH_6_MHZ
:
std
=
V4L2_STD_DTV_6MHZ
;
case
BANDWIDTH_6_MHZ
:
/* FIXME: Should allow select also ATSC */
type
|=
DTV6_QAM
;
break
;
default:
tuner_info
(
"error: bandwidth not supported.
\n
"
);
default:
tuner_info
(
"error: bandwidth not supported.
\n
"
);
};
priv
->
bandwidth
=
bandwidth
;
}
/* Load INIT1, if needed */
tuner_info
(
"Trying to load init1 firmware
\n
"
);
type0
=
BASE
|
INIT1
|
priv
->
ctrl
.
type
;
if
(
priv
->
ctrl
.
type
==
XC2028_FIRM_MTS
)
type0
|=
MTS
;
/* FIXME: Should handle errors - if INIT1 found */
rc
=
load_firmware
(
fe
,
type0
,
&
std0
);
/* FIXME: Should add support for FM radio
*/
if
(
priv
->
ctrl
.
type
==
XC2028_FIRM_MTS
)
type
|=
MTS
;
tuner_info
(
"firmware standard to load: %08lx
\n
"
,(
unsigned
long
)
std
);
if
(
priv
->
firm_type
&
std
)
{
tuner_info
(
"
xc3028:
no need to load a std-specific firmware.
\n
"
);
tuner_info
(
"no need to load a std-specific firmware.
\n
"
);
return
0
;
}
rc
=
load_firmware
(
fe
,
firmware_INIT1
);
if
(
std
&
V4L2_STD_MN
)
name
=
firmware_MN
;
else
if
(
std
&
V4L2_STD_DTV_6MHZ
)
name
=
firmware_6M
;
else
if
(
std
&
V4L2_STD_DTV_7MHZ
)
name
=
firmware_7M
;
else
if
(
std
&
V4L2_STD_DTV_8MHZ
)
name
=
firmware_8M
;
else
if
(
std
&
V4L2_STD_PAL_B
)
name
=
firmware_B
;
else
name
=
firmware_DK
;
tuner_info
(
"loading firmware named %s.
\n
"
,
name
);
rc
=
load_firmware
(
fe
,
name
);
rc
=
load_firmware
(
fe
,
type
,
&
std
);
if
(
rc
<
0
)
return
rc
;
...
...
@@ -341,11 +537,11 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */,
tuner_info
(
"%s called
\n
"
,
__FUNCTION__
);
mutex_lock
(
&
priv
->
lock
);
/* HACK: It seems that specific firmware need to be reloaded
when freq is changed */
mutex_lock
(
&
priv
->
lock
);
priv
->
firm_type
=
0
;
/* Reset GPIO 1 */
...
...
@@ -365,7 +561,13 @@ static int generic_set_tv_freq(struct dvb_frontend *fe, u32 freq /* in Hz */,
div
=
(
freq
-
offset
+
DIV
/
2
)
/
DIV
;
/* CMD= Set frequency */
send_seq
(
priv
,
{
0x00
,
0x02
,
0x00
,
0x00
});
if
(
priv
->
version
<
0x0202
)
{
send_seq
(
priv
,
{
0x00
,
0x02
,
0x00
,
0x00
});
}
else
{
send_seq
(
priv
,
{
0x80
,
0x02
,
0x00
,
0x00
});
}
rc
=
priv
->
tuner_callback
(
priv
->
video_dev
,
XC2028_RESET_CLK
,
1
);
if
(
rc
<
0
)
goto
ret
;
...
...
@@ -436,8 +638,13 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
priv
->
count
--
;
if
(
!
priv
->
count
)
if
(
!
priv
->
count
)
{
if
(
priv
->
ctrl
.
fname
)
kfree
(
priv
->
ctrl
.
fname
);
free_firmware
(
priv
);
kfree
(
priv
);
}
return
0
;
}
...
...
@@ -453,6 +660,32 @@ static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
return
0
;
}
static
int
xc2028_set_config
(
struct
dvb_frontend
*
fe
,
void
*
priv_cfg
)
{
struct
xc2028_data
*
priv
=
fe
->
tuner_priv
;
struct
xc2028_ctrl
*
p
=
priv_cfg
;
tuner_info
(
"%s called
\n
"
,
__FUNCTION__
);
priv
->
ctrl
.
type
=
p
->
type
;
if
(
p
->
fname
)
{
if
(
priv
->
ctrl
.
fname
)
kfree
(
priv
->
ctrl
.
fname
);
priv
->
ctrl
.
fname
=
kmalloc
(
strlen
(
p
->
fname
)
+
1
,
GFP_KERNEL
);
if
(
!
priv
->
ctrl
.
fname
)
return
-
ENOMEM
;
free_firmware
(
priv
);
strcpy
(
priv
->
ctrl
.
fname
,
p
->
fname
);
}
tuner_info
(
"%s OK
\n
"
,
__FUNCTION__
);
return
0
;
}
static
const
struct
dvb_tuner_ops
xc2028_dvb_tuner_ops
=
{
.
info
=
{
.
name
=
"Xceive XC3028"
,
...
...
@@ -461,6 +694,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
.
frequency_step
=
50000
,
},
.
set_config
=
xc2028_set_config
,
.
set_analog_params
=
xc2028_set_tv_freq
,
.
release
=
xc2028_dvb_release
,
.
get_frequency
=
xc2028_get_frequency
,
...
...
@@ -513,6 +747,8 @@ int xc2028_attach(struct dvb_frontend *fe, struct i2c_adapter* i2c_adap,
priv
->
dev
=
dev
;
priv
->
video_dev
=
video_dev
;
priv
->
tuner_callback
=
tuner_callback
;
priv
->
max_len
=
13
;
mutex_init
(
&
priv
->
lock
);
...
...
drivers/media/video/tuner-xc2028.h
浏览文件 @
de3fe21b
...
...
@@ -9,13 +9,22 @@
#include "dvb_frontend.h"
#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
enum
xc2028_firm_type
{
XC2028_FIRM_NORMAL
,
XC2028_FIRM_MTS
,
};
struct
xc2028_ctrl
{
enum
xc2028_firm_type
type
;
char
*
fname
;
};
/* xc2028 commands for callback */
#define XC2028_TUNER_RESET 0
#define XC2028_RESET_CLK 1
struct
dvb_frontend
;
struct
i2c_client
;
#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE))
int
xc2028_attach
(
struct
dvb_frontend
*
fe
,
struct
i2c_adapter
*
i2c_adap
,
u8
i2c_addr
,
struct
device
*
dev
,
void
*
video_dev
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录