[media] si470x: add control event support and more v4l2 compliancy fixes
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
4967d53dbb
commit
eae63ae007
@@ -262,7 +262,7 @@ static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
|
|||||||
*/
|
*/
|
||||||
int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
|
int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
|
||||||
{
|
{
|
||||||
unsigned int spacing, band_bottom;
|
unsigned int spacing, band_bottom, band_top;
|
||||||
unsigned short chan;
|
unsigned short chan;
|
||||||
|
|
||||||
/* Spacing (kHz) */
|
/* Spacing (kHz) */
|
||||||
@@ -278,19 +278,26 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
|
|||||||
spacing = 0.050 * FREQ_MUL; break;
|
spacing = 0.050 * FREQ_MUL; break;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Bottom of Band (MHz) */
|
/* Bottom/Top of Band (MHz) */
|
||||||
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
|
switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
|
||||||
/* 0: 87.5 - 108 MHz (USA, Europe) */
|
/* 0: 87.5 - 108 MHz (USA, Europe) */
|
||||||
case 0:
|
case 0:
|
||||||
band_bottom = 87.5 * FREQ_MUL; break;
|
band_bottom = 87.5 * FREQ_MUL;
|
||||||
|
band_top = 108 * FREQ_MUL;
|
||||||
|
break;
|
||||||
/* 1: 76 - 108 MHz (Japan wide band) */
|
/* 1: 76 - 108 MHz (Japan wide band) */
|
||||||
default:
|
default:
|
||||||
band_bottom = 76 * FREQ_MUL; break;
|
band_bottom = 76 * FREQ_MUL;
|
||||||
|
band_top = 108 * FREQ_MUL;
|
||||||
|
break;
|
||||||
/* 2: 76 - 90 MHz (Japan) */
|
/* 2: 76 - 90 MHz (Japan) */
|
||||||
case 2:
|
case 2:
|
||||||
band_bottom = 76 * FREQ_MUL; break;
|
band_bottom = 76 * FREQ_MUL;
|
||||||
|
band_top = 90 * FREQ_MUL;
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
freq = clamp(freq, band_bottom, band_top);
|
||||||
/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
|
/* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
|
||||||
chan = (freq - band_bottom) / spacing;
|
chan = (freq - band_bottom) / spacing;
|
||||||
|
|
||||||
@@ -515,17 +522,19 @@ static unsigned int si470x_fops_poll(struct file *file,
|
|||||||
struct poll_table_struct *pts)
|
struct poll_table_struct *pts)
|
||||||
{
|
{
|
||||||
struct si470x_device *radio = video_drvdata(file);
|
struct si470x_device *radio = video_drvdata(file);
|
||||||
int retval = 0;
|
unsigned long req_events = poll_requested_events(pts);
|
||||||
|
int retval = v4l2_ctrl_poll(file, pts);
|
||||||
|
|
||||||
/* switch on rds reception */
|
if (req_events & (POLLIN | POLLRDNORM)) {
|
||||||
|
/* switch on rds reception */
|
||||||
|
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
|
||||||
|
si470x_rds_on(radio);
|
||||||
|
|
||||||
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
|
poll_wait(file, &radio->read_queue, pts);
|
||||||
si470x_rds_on(radio);
|
|
||||||
|
|
||||||
poll_wait(file, &radio->read_queue, pts);
|
if (radio->rd_index != radio->wr_index)
|
||||||
|
retval |= POLLIN | POLLRDNORM;
|
||||||
if (radio->rd_index != radio->wr_index)
|
}
|
||||||
retval = POLLIN | POLLRDNORM;
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -637,6 +646,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
|
|||||||
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
|
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
|
||||||
/* the ideal factor is 0xffff/75 = 873,8 */
|
/* the ideal factor is 0xffff/75 = 873,8 */
|
||||||
tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
|
tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
|
||||||
|
if (tuner->signal > 0xffff)
|
||||||
|
tuner->signal = 0xffff;
|
||||||
|
|
||||||
/* automatic frequency control: -1: freq to low, 1 freq to high */
|
/* automatic frequency control: -1: freq to low, 1 freq to high */
|
||||||
/* AFCRL does only indicate that freq. differs, not if too low/high */
|
/* AFCRL does only indicate that freq. differs, not if too low/high */
|
||||||
@@ -660,7 +671,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (tuner->index != 0)
|
if (tuner->index != 0)
|
||||||
goto done;
|
return -EINVAL;
|
||||||
|
|
||||||
/* mono/stereo selector */
|
/* mono/stereo selector */
|
||||||
switch (tuner->audmode) {
|
switch (tuner->audmode) {
|
||||||
@@ -668,15 +679,13 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
|
|||||||
radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
|
radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
|
||||||
break;
|
break;
|
||||||
case V4L2_TUNER_MODE_STEREO:
|
case V4L2_TUNER_MODE_STEREO:
|
||||||
|
default:
|
||||||
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
|
radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = si470x_set_register(radio, POWERCFG);
|
retval = si470x_set_register(radio, POWERCFG);
|
||||||
|
|
||||||
done:
|
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
dev_warn(&radio->videodev.dev,
|
dev_warn(&radio->videodev.dev,
|
||||||
"set tuner failed with %d\n", retval);
|
"set tuner failed with %d\n", retval);
|
||||||
@@ -770,6 +779,8 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
|
|||||||
.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,
|
.vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
|
||||||
|
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
||||||
|
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user