<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:times new roman,new york,times,serif;font-size:12pt"><div style="font-family: times new roman,new york,times,serif; font-size: 12pt;"><br><br><div style="font-family: times new roman,new york,times,serif; font-size: 12pt;">----- Original Message ----<br>From: Chaogui Zhang <czhang1974@gmail.com><br>To: linux-dvb@linuxtv.org<br>Sent: Monday, January 28, 2008 11:20:10 AM<br>Subject: Re: [linux-dvb] [PATCH] XC5000 tuner improvement/clean up<br><br>
On
Jan
27,
2008
6:50
PM,
Chaogui
Zhang
<<a ymailto="mailto:czhang1974@gmail.com" href="mailto:czhang1974@gmail.com">czhang1974@gmail.com</a>>
wrote:<br>> <br>>
Download
the
newest
v4l-dvb
tree
from
<a href="http://linuxtv.org/hg/v4l-dvb" target="_blank">http://linuxtv.org/hg/v4l-dvb</a><br>>
and
apply
the
patch
against
it.<br>> <br><br>I
just
noticed
that
the
previous
patch
that
fixed
the
kernel
oops
has<br>been
merged
into
the
master
tree,
which
conflicts
with
the
patch
for <br>tuner
performance
improvement(which
contains
the
oops
fixes
too).
I<br>regenerated
the
patch
against
the
master
tree
and
it
is
below.
Please<br>use
this
one
instead.<br><br>-- <br>Chaogui
Zhang<br><br>Signed-off-by:
Chaogui
Zhang
<<a ymailto="mailto:czhang1974@gmail.com" href="mailto:czhang1974@gmail.com">czhang1974@gmail.com</a>><br><br>diff
-r
ed7daeb29425
linux/drivers/media/dvb/frontends/xc5000.c<br>---
a/linux/drivers/media/dvb/frontends/xc5000.c
Mon
Jan
28
10:01:11
2008
-0200<br>+++
b/linux/drivers/media/dvb/frontends/xc5000.c
Sun
Jan
27
19:36:07
2008
-0500<br>@@
-3,6
+3,7
@@<br>
*<br>
*
Copyright
(c)
2007
Xceive
Corporation<br>
*
Copyright
(c)
2007
Steven
Toth
<<a ymailto="mailto:stoth@hauppauge.com" href="mailto:stoth@hauppauge.com">stoth@hauppauge.com</a>><br>+
*
Copyright
(c)
2007,
2008
Chaogui
Zhang
<<a ymailto="mailto:czhang1974@gmail.com" href="mailto:czhang1974@gmail.com">czhang1974@gmail.com</a>><br>
*<br>
*
This
program
is
free
software;
you
can
redistribute
it
and/or
modify<br>
*
it
under
the
terms
of
the
GNU
General
Public
License
as
published
by<br>@@
-38,6
+39,13
@@
MODULE_PARM_DESC(debug,
"Turn
on/off
deb<br> <br>
#define
dprintk(level,fmt,
arg...)
if
(debug
>=
level)
\<br>
printk(KERN_INFO
"%s:
"
fmt,
"xc5000",
##
arg)<br>+<br>+static
int
allow_shutdown;<br>+module_param(allow_shutdown,
int,
0644);<br>+MODULE_PARM_DESC(allow_shutdown,
"Allow
the
XC5000
tuner
to
be
shutdown
(default:
no).");<br>+<br>+static
LIST_HEAD(xc5000_list);<br>+static
DEFINE_MUTEX(xc5000_list_lock);<br> <br>
#define
XC5000_DEFAULT_FIRMWARE
"dvb-fe-xc5000-1.1.fw"<br>
#define
XC5000_DEFAULT_FIRMWARE_SIZE
12332<br>@@
-179,7
+187,6
@@
XC_TV_STANDARD
XC5000_Standard[MAX_TV_ST<br> <br>
static
int
xc5000_writeregs(struct
xc5000_priv
*priv,
u8
*buf,
u8
len);<br>
static
int
xc5000_readregs(struct
xc5000_priv
*priv,
u8
*buf,
u8
len);<br>-static
void
xc5000_TunerReset(struct
dvb_frontend
*fe);<br> <br>
static
int
xc_send_i2c_data(struct
xc5000_priv
*priv,
u8
*buf,
int
len)<br>
{<br>@@
-195,29
+202,21
@@
static
int
xc_read_i2c_data(struct
xc500<br> <br>
static
int
xc_reset(struct
dvb_frontend
*fe)<br>
{<br>-
xc5000_TunerReset(fe);<br>-
return
XC_RESULT_SUCCESS;<br>-}<br>-<br>-static
void
xc_wait(int
wait_ms)<br>-{<br>-
msleep(wait_ms);<br>-}<br>-<br>-static
void
xc5000_TunerReset(struct
dvb_frontend
*fe)<br>-{<br>
struct
xc5000_priv
*priv
=
fe->tuner_priv;<br>
int
ret;<br> <br>
dprintk(1,
"%s()\n",
__FUNCTION__);<br> <br>-
if
(priv->cfg->tuner_callback)
{<br>-
ret
=
priv->cfg->tuner_callback(priv->cfg->priv,<br>-
XC5000_TUNER_RESET,
0);<br>-
if
(ret)<br>-
printk(KERN_ERR
"xc5000:
reset
failed\n");<br>-
}
else<br>-
printk(KERN_ERR
"xc5000:
no
tuner
reset
callback
function,
fatal\n");<br>+
if
(!priv->cfg->tuner_callback)
{<br>+
printk(KERN_ERR<br>+
"xc5000:
no
tuner
reset
callback
function,
fatal\n");<br>+
return
XC_RESULT_RESET_FAILURE;<br>+
}<br>+<br>+
ret
=
priv->cfg->tuner_callback(priv->cfg->priv,<br>+
XC5000_TUNER_RESET,
0);<br>+
if
(ret)
printk(KERN_ERR
"xc5000:
reset
failed\n");<br>+
return
ret;<br>
}<br> <br>
static
int
xc_write_reg(struct
xc5000_priv
*priv,
u16
regAddr,
u16
i2cData)<br>@@
-245,7
+244,7
@@
static
int
xc_write_reg(struct
xc5000_pr<br>
/*
busy
flag
cleared
*/<br>
break;<br>
}
else
{<br>-
xc_wait(100);
/*
wait
5
ms
*/<br>+
msleep(5);
/*
wait
5
ms
*/<br>
WatchDogTimer--;<br>
}<br>
}<br>@@
-296,7
+295,7
@@
static
int
xc_load_i2c_sequence(struct
d<br>
return
result;<br>
}
else
if
(len
&
0x8000)
{<br>
/*
WAIT
command
*/<br>-
xc_wait(len
&
0x7FFF);<br>+
msleep(len
&
0x7FFF);<br>
index
+=
2;<br>
}
else
{<br>
/*
Send
i2c
data
whilst
ensuring
individual
transactions<br>@@
-352,11
+351,10
@@
static
int
xc_SetTVStandard(struct
xc500<br> <br>
static
int
xc_shutdown(struct
xc5000_priv
*priv)<br>
{<br>-
return
0;<br>-
/*
Fixme:
cannot
bring
tuner
back
alive
once
shutdown<br>-
*
without
reloading
the
driver
modules.<br>-
*
return
xc_write_reg(priv,
XREG_POWER_DOWN,
0);<br>-
*/<br>+
if(allow_shutdown)<br>+
return
xc_write_reg(priv,
XREG_POWER_DOWN,
0);<br>+
else<br>+
return
0;<br>
}<br> <br>
static
int
xc_SetSignalSource(struct
xc5000_priv
*priv,
u16
rf_mode)<br>@@
-496,7
+494,7
@@
static
u16
WaitForLock(struct
xc5000_pri<br>
while
((lockState
==
0)
&&
(watchDogCount
>
0))
{<br>
xc_get_lock_status(priv,
&lockState);<br>
if
(lockState
!=
1)
{<br>-
xc_wait(5);<br>+
msleep(5);<br>
watchDogCount--;<br>
}<br>
}<br>@@
-612,7
+610,7
@@
static
void
xc_debug_dump(struct
xc5000_<br>
*
Frame
Lines
needs
two
frame
times
after
initial
lock<br>
*
before
it
is
valid.<br>
*/<br>-
xc_wait(100);<br>+
msleep(100);<br> <br>
xc_get_ADC_Envelope(priv,
&adc_envelope);<br>
dprintk(1,
"***
ADC
envelope
(0-1023)
=
%d\n",
adc_envelope);<br>@@
-640,13
+638,32
@@
static
void
xc_debug_dump(struct
xc5000_<br>
dprintk(1,
"***
Quality
(0:<8dB,
7:>56dB)
=
%d\n",
quality);<br>
}<br> <br>+static
int
xc_load_fw_and_init_tuner(struct
dvb_frontend
*fe);<br>+<br>
static
int
xc5000_set_params(struct
dvb_frontend
*fe,<br>
struct
dvb_frontend_parameters
*params)<br>
{<br>
struct
xc5000_priv
*priv
=
fe->tuner_priv;<br>-
int
ret;<br>+
int
ret=0;<br> <br>
dprintk(1,
"%s()
frequency=%d
(Hz)\n",
__FUNCTION__,
params->frequency);<br>+<br>+
mutex_lock(&priv->lock);<br>+<br>+
if(priv->fwloaded
==
0)
{<br>+
ret
=
xc_load_fw_and_init_tuner(fe);<br>+
}<br>+#if
0<br>+
else
{<br>+
ret
=
xc_initialize(priv);<br>+
msleep(100);<br>+
}<br>+#endif<br>+
if(ret
!=
XC_RESULT_SUCCESS)
{<br>+
printk(KERN_ERR
"xc5000:
Unable
to
initialise
tuner\n");<br>+
mutex_unlock(&priv->lock);<br>+
return
-EREMOTEIO;<br>+
}<br> <br>
switch(params->u.vsb.modulation)
{<br>
case
VSB_8:<br>@@
-667,6
+684,7
@@
static
int
xc5000_set_params(struct
dvb_<br>
priv->video_standard
=
DTV6;<br>
break;<br>
default:<br>+
mutex_unlock(&priv->lock);<br>
return
-EINVAL;<br>
}<br> <br>@@
-678,6
+696,7
@@
static
int
xc5000_set_params(struct
dvb_<br>
printk(KERN_ERR<br>
"xc5000:
xc_SetSignalSource(%d)
failed\n",<br>
priv->rf_mode);<br>+
mutex_unlock(&priv->lock);<br>
return
-EREMOTEIO;<br>
}<br> <br>@@
-686,6
+705,7
@@
static
int
xc5000_set_params(struct
dvb_<br>
XC5000_Standard[priv->video_standard].AudioMode);<br>
if
(ret
!=
XC_RESULT_SUCCESS)
{<br>
printk(KERN_ERR
"xc5000:
xc_SetTVStandard
failed\n");<br>+
mutex_unlock(&priv->lock);<br>
return
-EREMOTEIO;<br>
}<br> <br>@@
-693,6
+713,7
@@
static
int
xc5000_set_params(struct
dvb_<br>
if
(ret
!=
XC_RESULT_SUCCESS)
{<br>
printk(KERN_ERR
"xc5000:
xc_Set_IF_frequency(%d)
failed\n",<br>
priv->cfg->if_khz);<br>+
mutex_unlock(&priv->lock);<br>
return
-EIO;<br>
}<br> <br>@@
-701,22
+722,36
@@
static
int
xc5000_set_params(struct
dvb_<br>
if
(debug)<br>
xc_debug_dump(priv);<br> <br>-
return
0;<br>-}<br>-<br>-static
int
xc_load_fw_and_init_tuner(struct
dvb_frontend
*fe);<br>+
mutex_unlock(&priv->lock);<br>+
return
0;<br>+}<br> <br>
static
int
xc5000_set_analog_params(struct
dvb_frontend
*fe,<br>
struct
analog_parameters
*params)<br>
{<br>
struct
xc5000_priv
*priv
=
fe->tuner_priv;<br>-
int
ret;<br>-<br>-
if(priv->fwloaded
==
0)<br>-
xc_load_fw_and_init_tuner(fe);<br>+
int
ret=0;<br> <br>
dprintk(1,
"%s()
frequency=%d
(in
units
of
62.5khz)\n",<br>
__FUNCTION__,
params->frequency);<br>+<br>+
mutex_lock(&priv->lock);<br>+<br>+
if(priv->fwloaded
==
0)
{<br>+
ret
=
xc_load_fw_and_init_tuner(fe);<br>+
}<br>+#if
0<br>+
else
{<br>+
ret
=
xc_initialize(priv);<br>+
msleep(100);<br>+
}<br>+#endif<br>+<br>+
if(ret
!=
XC_RESULT_SUCCESS)
{<br>+
printk(KERN_ERR
"xc5000:
Unable
to
initialise
tuner\n");<br>+
mutex_unlock(&priv->lock);<br>+
return
-EREMOTEIO;<br>+
}<br> <br>
priv->rf_mode
=
XC_RF_MODE_CABLE;
/*
Fix
me:
it
could
be
air.
*/<br> <br>@@
-769,9
+804,10
@@
tune_channel:<br>
tune_channel:<br>
ret
=
xc_SetSignalSource(priv,
priv->rf_mode);<br>
if
(ret
!=
XC_RESULT_SUCCESS)
{<br>-
printk(KERN_ERR<br>+
printk(KERN_ERR<br>
"xc5000:
xc_SetSignalSource(%d)
failed\n",<br>
priv->rf_mode);<br>+
mutex_unlock(&priv->lock);<br>
return
-EREMOTEIO;<br>
}<br> <br>@@
-780,6
+816,7
@@
tune_channel:<br>
XC5000_Standard[priv->video_standard].AudioMode);<br>
if
(ret
!=
XC_RESULT_SUCCESS)
{<br>
printk(KERN_ERR
"xc5000:
xc_SetTVStandard
failed\n");<br>+
mutex_unlock(&priv->lock);<br>
return
-EREMOTEIO;<br>
}<br> <br>@@
-788,6
+825,7
@@
tune_channel:<br>
if
(debug)<br>
xc_debug_dump(priv);<br> <br>+
mutex_unlock(&priv->lock);<br>
return
0;<br>
}<br> <br>@@
-827,12
+865,11
@@
static
int
xc_load_fw_and_init_tuner(str<br>
struct
xc5000_priv
*priv
=
fe->tuner_priv;<br>
int
ret
=
0;<br> <br>-
if
(priv->fwloaded
==
0)
{<br>-
ret
=
xc5000_fwupload(fe);<br>-
if
(ret
!=
XC_RESULT_SUCCESS)<br>-
return
ret;<br>-
priv->fwloaded
=
1;<br>-
}<br>+
ret
=
xc5000_fwupload(fe);<br>+
if
(ret
!=
XC_RESULT_SUCCESS)
{<br>+
return
ret;<br>+
}<br>+
priv->fwloaded
=
1;<br> <br>
/*
Start
the
tuner
self-calibration
process
*/<br>
ret
|=
xc_initialize(priv);<br>@@
-842,7
+879,7
@@
static
int
xc_load_fw_and_init_tuner(str<br>
*
I2C
transactions
until
calibration
is
complete.
This
way
we<br>
*
don't
have
to
rely
on
clock
stretching
working.<br>
*/<br>-
xc_wait(
100
);<br>+
msleep(
100
);<br> <br>
/*
Default
to
"CABLE"
mode
*/<br>
ret
|=
xc_write_reg(priv,
XREG_SIGNALSOURCE,
XC_RF_MODE_CABLE);<br>@@
-857,21
+894,20
@@
static
int
xc5000_sleep(struct
dvb_front<br> <br>
dprintk(1,
"%s()\n",
__FUNCTION__);<br> <br>-
/*
On
Pinnacle
PCTV
HD
800i,
the
tuner
cannot
be
reinitialized<br>-
*
once
shutdown
without
reloading
the
driver.
Maybe
I
am
not<br>-
*
doing
something
right.<br>-
*<br>-
*/<br>+
mutex_lock(&priv->lock);<br> <br>
ret
=
xc_shutdown(priv);<br>
if(ret
!=
XC_RESULT_SUCCESS)
{<br>
printk(KERN_ERR<br>
"xc5000:
%s()
unable
to
shutdown
tuner\n",<br>
__FUNCTION__);<br>+
mutex_unlock(&priv->lock);<br>
return
-EREMOTEIO;<br>
}<br>
else
{<br>-
/*
priv->fwloaded
=
0;
*/<br>+
if(allow_shutdown) <br>+
priv->fwloaded
=
0;
/*
was
indeed
shutdown
*/<br>+
mutex_unlock(&priv->lock);<br>
return
XC_RESULT_SUCCESS;<br>
}<br>
}<br>@@
-879,24
+915,51
@@
static
int
xc5000_init(struct
dvb_fronte<br>
static
int
xc5000_init(struct
dvb_frontend
*fe)<br>
{<br>
struct
xc5000_priv
*priv
=
fe->tuner_priv;<br>+
int
ret;<br>+<br>
dprintk(1,
"%s()\n",
__FUNCTION__);<br> <br>-
if
(xc_load_fw_and_init_tuner(fe)
!=
XC_RESULT_SUCCESS)
{<br>+
mutex_lock(&priv->lock);<br>+<br>+
if(priv->fwloaded
==
0)
{<br>+
ret
=
xc_load_fw_and_init_tuner(fe);<br>+
}<br>+
else
{
/*
Firmware
has
been
loaded
previously,
just
initialize
*/<br>+
ret
=
xc_initialize(priv);<br>+
msleep(100);<br>+
ret
|=
xc_write_reg(priv,
XREG_SIGNALSOURCE,
XC_RF_MODE_CABLE);<br>+
}<br>+<br>+
if(ret
!=
XC_RESULT_SUCCESS)
{<br>
printk(KERN_ERR
"xc5000:
Unable
to
initialise
tuner\n");<br>+
mutex_unlock(&priv->lock);<br>
return
-EREMOTEIO;<br>
}<br> <br>
if
(debug)<br>
xc_debug_dump(priv);<br> <br>+
mutex_unlock(&priv->lock);<br>
return
0;<br>
}<br> <br>
static
int
xc5000_release(struct
dvb_frontend
*fe)<br>
{<br>+
struct
xc5000_priv
*priv
=
fe->tuner_priv;<br>+<br>
dprintk(1,
"%s()\n",
__FUNCTION__);<br>-
kfree(fe->tuner_priv);<br>+<br>+
mutex_lock(&xc5000_list_lock);<br>+ <br>+
priv->count--;<br>+
if(priv->count
==
0)
{<br>+
list_del(&priv->xc5000_list);<br>+
kfree(priv);<br>+
}<br>
fe->tuner_priv
=
NULL;<br>+<br>+
mutex_unlock(&xc5000_list_lock);<br>+<br>
return
0;<br>
}<br> <br>@@
-924,23
+987,49
@@
struct
dvb_frontend
*
xc5000_attach(stru<br>
struct
xc5000_config
*cfg)<br>
{<br>
struct
xc5000_priv
*priv
=
NULL;<br>+
void
*cfg_priv;<br>
u16
id
=
0;<br> <br>
dprintk(1,
"%s()\n",
__FUNCTION__);<br> <br>-
priv
=
kzalloc(sizeof(struct
xc5000_priv),
GFP_KERNEL);<br>-
if
(priv
==
NULL)<br>+
if
(NULL
==
cfg
||
NULL
==
cfg->priv
||
NULL
==
fe)<br>
return
NULL;<br> <br>-
priv->cfg
=
cfg;<br>-
priv->bandwidth
=
BANDWIDTH_6_MHZ;<br>-
priv->i2c
=
i2c;<br>+
cfg_priv
=
cfg->priv;<br>+<br>+
mutex_lock(&xc5000_list_lock);<br>+<br>+
list_for_each_entry(priv,
&xc5000_list,
xc5000_list)
{<br>+
if
(priv->cfg->priv
==
cfg->priv)
{<br>+
cfg_priv
=
NULL;<br>+
break;<br>+
}<br>+
}<br>+<br>+
if(cfg_priv)
{<br>+
priv
=
kzalloc(sizeof(struct
xc5000_priv),
GFP_KERNEL);<br>+
if
(priv
==
NULL)
{<br>+
mutex_unlock(&xc5000_list_lock);<br>+
return
NULL;<br>+
}<br>+<br>+
priv->cfg
=
cfg;<br>+
priv->bandwidth
=
BANDWIDTH_6_MHZ;<br>+
priv->i2c
=
i2c;<br>+
priv->fwloaded
=
0;<br>+
priv->count
=
0;<br>+<br>+
mutex_init(&priv->lock);<br>+
list_add_tail(&priv->xc5000_list,
&xc5000_list);<br>+
}<br>+<br> <br>
/*
Check
if
firmware
has
been
loaded.
It
is
possible
that
another<br>
instance
of
the
driver
has
loaded
the
firmware.<br>
*/<br>
if
(xc5000_readreg(priv,
XREG_PRODUCT_ID,
&id)
!=
0)
{<br>
kfree(priv);<br>+
mutex_unlock(&xc5000_list_lock);<br>
return
NULL;<br>
}<br> <br>@@
-966,6
+1055,7
@@
struct
dvb_frontend
*
xc5000_attach(stru<br>
"xc5000:
Device
not
found
at
addr
0x%02x
(0x%x)\n",<br>
cfg->i2c_address,
id);<br>
kfree(priv);<br>+
mutex_unlock(&xc5000_list_lock);<br>
return
NULL;<br>
}<br> <br>@@
-973,11
+1063,14
@@
struct
dvb_frontend
*
xc5000_attach(stru<br>
sizeof(struct
dvb_tuner_ops));<br> <br>
fe->tuner_priv
=
priv;<br>-<br>+
priv->count++;<br>+<br>+
mutex_unlock(&xc5000_list_lock);<br>
return
fe;<br>
}<br>
EXPORT_SYMBOL(xc5000_attach);<br> <br>
MODULE_AUTHOR("Steven
Toth");<br>+MODULE_AUTHOR("Chaogui
Zhang");<br>
MODULE_DESCRIPTION("Xceive
xc5000
silicon
tuner
driver");<br>
MODULE_LICENSE("GPL");<br>diff
-r
ed7daeb29425
linux/drivers/media/dvb/frontends/xc5000_priv.h<br>---
a/linux/drivers/media/dvb/frontends/xc5000_priv.h
Mon
Jan
28
10:01:11
2008
-0200<br>+++
b/linux/drivers/media/dvb/frontends/xc5000_priv.h
Fri
Jan
25
11:46:34
2008
-0500<br>@@
-23,6
+23,7
@@<br>
#define
XC5000_PRIV_H<br> <br>
struct
xc5000_priv
{<br>+
struct
list_head
xc5000_list;<br>
struct
xc5000_config
*cfg;<br>
struct
i2c_adapter
*i2c;<br> <br>@@
-31,6
+32,14
@@
struct
xc5000_priv
{<br>
u8
video_standard;<br>
u8
rf_mode;<br>
u8
fwloaded;<br>+<br>+
int
count;<br>+<br>+#if
LINUX_VERSION_CODE
>=
KERNEL_VERSION(2,
6,
16)<br>+
struct
mutex
lock;<br>+#else<br>+
struct
semaphore
lock;<br>+#endif<br>
};<br> <br>
#endif<br><br>Greeting Chaogui,<br>I have been reading about the patch clean up for the xc5000 tuner. I am still new to the whole driver making and the like. My question is how do I apply this clean up? I have a pinnicale 800i card, and had to get this in order to get my tuner card working. Any assistance would be greatly appreciated.<br>Thanks,<br>Ed<br>_______________________________________________<br>linux-dvb
mailing
list<br><a ymailto="mailto:linux-dvb@linuxtv.org" href="mailto:linux-dvb@linuxtv.org">linux-dvb@linuxtv.org</a><br><a href="http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb" target="_blank">http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb</a><br></div><br></div></div><br>
<hr size=1>Looking for last minute shopping deals? <a href="http://us.rd.yahoo.com/evt=51734/*http://tools.search.yahoo.com/newsearch/category.php?category=shopping">
Find them fast with Yahoo! Search.</a></body></html>