V4L/DVB (7997): si470x: hardware frequency seek support
This patch brings the following changes: - this now finally adds hardware frequency seek support Signed-off-by: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
ace7d4bbe6
commit
bbc8995f9f
|
@ -101,11 +101,11 @@
|
||||||
* - unplugging fixed
|
* - unplugging fixed
|
||||||
* 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
|
* 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
|
||||||
* Version 1.0.8
|
* Version 1.0.8
|
||||||
|
* - hardware frequency seek support
|
||||||
* - afc indication
|
* - afc indication
|
||||||
* - more safety checks, let si470x_get_freq return errno
|
* - more safety checks, let si470x_get_freq return errno
|
||||||
*
|
*
|
||||||
* ToDo:
|
* ToDo:
|
||||||
* - add seeking support
|
|
||||||
* - add firmware download/update support
|
* - add firmware download/update support
|
||||||
* - RDS support: interrupt mode, instead of polling
|
* - RDS support: interrupt mode, instead of polling
|
||||||
* - add LED status output (check if that's not already done in firmware)
|
* - add LED status output (check if that's not already done in firmware)
|
||||||
|
@ -192,6 +192,11 @@ static unsigned int tune_timeout = 3000;
|
||||||
module_param(tune_timeout, uint, 0);
|
module_param(tune_timeout, uint, 0);
|
||||||
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
|
MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
|
||||||
|
|
||||||
|
/* Seek timeout */
|
||||||
|
static unsigned int seek_timeout = 5000;
|
||||||
|
module_param(seek_timeout, uint, 0);
|
||||||
|
MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
|
||||||
|
|
||||||
/* RDS buffer blocks */
|
/* RDS buffer blocks */
|
||||||
static unsigned int rds_buf = 100;
|
static unsigned int rds_buf = 100;
|
||||||
module_param(rds_buf, uint, 0);
|
module_param(rds_buf, uint, 0);
|
||||||
|
@ -726,6 +731,62 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* si470x_set_seek - set seek
|
||||||
|
*/
|
||||||
|
static int si470x_set_seek(struct si470x_device *radio,
|
||||||
|
unsigned int wrap_around, unsigned int seek_upward)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
unsigned long timeout;
|
||||||
|
bool timed_out = 0;
|
||||||
|
|
||||||
|
/* start seeking */
|
||||||
|
radio->registers[POWERCFG] |= POWERCFG_SEEK;
|
||||||
|
if (wrap_around == 1)
|
||||||
|
radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
|
||||||
|
else
|
||||||
|
radio->registers[POWERCFG] |= POWERCFG_SKMODE;
|
||||||
|
if (seek_upward == 1)
|
||||||
|
radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
|
||||||
|
else
|
||||||
|
radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
|
||||||
|
retval = si470x_set_register(radio, POWERCFG);
|
||||||
|
if (retval < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* wait till seek operation has completed */
|
||||||
|
timeout = jiffies + msecs_to_jiffies(seek_timeout);
|
||||||
|
do {
|
||||||
|
retval = si470x_get_register(radio, STATUSRSSI);
|
||||||
|
if (retval < 0)
|
||||||
|
goto stop;
|
||||||
|
timed_out = time_after(jiffies, timeout);
|
||||||
|
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
|
||||||
|
(!timed_out));
|
||||||
|
if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
|
||||||
|
printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n");
|
||||||
|
if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
|
||||||
|
printk(KERN_WARNING DRIVER_NAME
|
||||||
|
": seek failed / band limit reached\n");
|
||||||
|
if (timed_out)
|
||||||
|
printk(KERN_WARNING DRIVER_NAME
|
||||||
|
": seek timed out after %u ms\n", seek_timeout);
|
||||||
|
|
||||||
|
stop:
|
||||||
|
/* stop seeking */
|
||||||
|
radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
|
||||||
|
retval = si470x_set_register(radio, POWERCFG);
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* try again, if timed out */
|
||||||
|
if ((retval == 0) && timed_out)
|
||||||
|
retval = -EAGAIN;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* si470x_start - switch on radio
|
* si470x_start - switch on radio
|
||||||
*/
|
*/
|
||||||
|
@ -1148,7 +1209,8 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
|
||||||
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
|
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
|
||||||
sprintf(capability->bus_info, "USB");
|
sprintf(capability->bus_info, "USB");
|
||||||
capability->version = DRIVER_KERNEL_VERSION;
|
capability->version = DRIVER_KERNEL_VERSION;
|
||||||
capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
|
capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
|
||||||
|
V4L2_CAP_TUNER | V4L2_CAP_RADIO;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1494,6 +1556,36 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
|
||||||
|
*/
|
||||||
|
static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
|
||||||
|
struct v4l2_hw_freq_seek *seek)
|
||||||
|
{
|
||||||
|
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
/* safety checks */
|
||||||
|
if (radio->disconnected) {
|
||||||
|
retval = -EIO;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
|
||||||
|
retval = -EINVAL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (retval < 0)
|
||||||
|
printk(KERN_WARNING DRIVER_NAME
|
||||||
|
": set hardware frequency seek failed with %d\n",
|
||||||
|
retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* si470x_viddev_tamples - video device interface
|
* si470x_viddev_tamples - video device interface
|
||||||
*/
|
*/
|
||||||
|
@ -1514,6 +1606,7 @@ static struct video_device si470x_viddev_template = {
|
||||||
.vidioc_s_tuner = si470x_vidioc_s_tuner,
|
.vidioc_s_tuner = si470x_vidioc_s_tuner,
|
||||||
.vidioc_g_frequency = si470x_vidioc_g_frequency,
|
.vidioc_g_frequency = si470x_vidioc_g_frequency,
|
||||||
.vidioc_s_frequency = si470x_vidioc_s_frequency,
|
.vidioc_s_frequency = si470x_vidioc_s_frequency,
|
||||||
|
.vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue