diff options
author | Mike Isely <isely@pobox.com> | 2007-01-19 22:09:47 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-02-21 10:34:38 -0500 |
commit | 18103c57b0168ebc0401702d483fe131f0aecc7a (patch) | |
tree | 1d57e73217254121f0c023009c510a4936332d64 /drivers/media/video/pvrusb2 | |
parent | af78a48b69231e129db0e1db24053da22f8eed6d (diff) |
V4L/DVB (5081): Pvrusb2: VIDIOC_G_TUNER cleanup
Clean up use of VIDIOC_G_TUNER; we now correctly gather info from all
the I2C client modules. Also abide by V4L2_TUNER_CAP_LOW
appropriately.
Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pvrusb2')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-audio.c | 24 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 13 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | 16 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 99 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.h | 13 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | 1 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | 19 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | 1 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | 22 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-i2c-core.h | 3 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 85 | ||||
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | 13 |
12 files changed, 144 insertions, 165 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index 122496f36845..5d30c9366144 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c | |||
@@ -31,7 +31,6 @@ struct pvr2_msp3400_handler { | |||
31 | struct pvr2_hdw *hdw; | 31 | struct pvr2_hdw *hdw; |
32 | struct pvr2_i2c_client *client; | 32 | struct pvr2_i2c_client *client; |
33 | struct pvr2_i2c_handler i2c_handler; | 33 | struct pvr2_i2c_handler i2c_handler; |
34 | struct pvr2_audio_stat astat; | ||
35 | unsigned long stale_mask; | 34 | unsigned long stale_mask; |
36 | }; | 35 | }; |
37 | 36 | ||
@@ -126,27 +125,9 @@ static void msp3400_update(struct pvr2_msp3400_handler *ctxt) | |||
126 | } | 125 | } |
127 | 126 | ||
128 | 127 | ||
129 | /* This reads back the current signal type */ | ||
130 | static int get_audio_status(struct pvr2_msp3400_handler *ctxt) | ||
131 | { | ||
132 | struct v4l2_tuner vt; | ||
133 | int stat; | ||
134 | |||
135 | memset(&vt,0,sizeof(vt)); | ||
136 | stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); | ||
137 | if (stat < 0) return stat; | ||
138 | |||
139 | ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0; | ||
140 | ctxt->hdw->flag_bilingual = | ||
141 | (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | |||
146 | static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) | 128 | static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) |
147 | { | 129 | { |
148 | ctxt->client->handler = NULL; | 130 | ctxt->client->handler = NULL; |
149 | ctxt->hdw->audio_stat = NULL; | ||
150 | kfree(ctxt); | 131 | kfree(ctxt); |
151 | } | 132 | } |
152 | 133 | ||
@@ -169,7 +150,6 @@ static const struct pvr2_i2c_handler_functions msp3400_funcs = { | |||
169 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | 150 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) |
170 | { | 151 | { |
171 | struct pvr2_msp3400_handler *ctxt; | 152 | struct pvr2_msp3400_handler *ctxt; |
172 | if (hdw->audio_stat) return 0; | ||
173 | if (cp->handler) return 0; | 153 | if (cp->handler) return 0; |
174 | 154 | ||
175 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); | 155 | ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); |
@@ -180,13 +160,9 @@ int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
180 | ctxt->i2c_handler.func_table = &msp3400_funcs; | 160 | ctxt->i2c_handler.func_table = &msp3400_funcs; |
181 | ctxt->client = cp; | 161 | ctxt->client = cp; |
182 | ctxt->hdw = hdw; | 162 | ctxt->hdw = hdw; |
183 | ctxt->astat.ctxt = ctxt; | ||
184 | ctxt->astat.status = (int (*)(void *))get_audio_status; | ||
185 | ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach; | ||
186 | ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/ | 163 | ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/ |
187 | sizeof(msp3400_ops[0]))) - 1; | 164 | sizeof(msp3400_ops[0]))) - 1; |
188 | cp->handler = &ctxt->i2c_handler; | 165 | cp->handler = &ctxt->i2c_handler; |
189 | hdw->audio_stat = &ctxt->astat; | ||
190 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", | 166 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", |
191 | cp->client->addr); | 167 | cp->client->addr); |
192 | return !0; | 168 | return !0; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index c2a154e4ec59..a3357bf2a1af 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -199,18 +199,6 @@ static int decoder_detect(struct pvr2_i2c_client *cp) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | 201 | ||
202 | static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt) | ||
203 | { | ||
204 | struct v4l2_tuner vt; | ||
205 | int ret; | ||
206 | |||
207 | memset(&vt,0,sizeof(vt)); | ||
208 | ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); | ||
209 | if (ret < 0) return -EINVAL; | ||
210 | return vt.signal ? 1 : 0; | ||
211 | } | ||
212 | |||
213 | |||
214 | static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, | 202 | static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, |
215 | char *buf,unsigned int cnt) | 203 | char *buf,unsigned int cnt) |
216 | { | 204 | { |
@@ -252,7 +240,6 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, | |||
252 | ctxt->ctrl.ctxt = ctxt; | 240 | ctxt->ctrl.ctxt = ctxt; |
253 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; | 241 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; |
254 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; | 242 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; |
255 | ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; | ||
256 | ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; | 243 | ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; |
257 | ctxt->client = cp; | 244 | ctxt->client = cp; |
258 | ctxt->hdw = hdw; | 245 | ctxt->hdw = hdw; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index b9df52c882a8..bc911ff75306 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -137,17 +137,10 @@ struct pvr2_ctrl { | |||
137 | }; | 137 | }; |
138 | 138 | ||
139 | 139 | ||
140 | struct pvr2_audio_stat { | ||
141 | void *ctxt; | ||
142 | void (*detach)(void *); | ||
143 | int (*status)(void *); | ||
144 | }; | ||
145 | |||
146 | struct pvr2_decoder_ctrl { | 140 | struct pvr2_decoder_ctrl { |
147 | void *ctxt; | 141 | void *ctxt; |
148 | void (*detach)(void *); | 142 | void (*detach)(void *); |
149 | void (*enable)(void *,int); | 143 | void (*enable)(void *,int); |
150 | int (*tuned)(void *); | ||
151 | void (*force_reset)(void *); | 144 | void (*force_reset)(void *); |
152 | }; | 145 | }; |
153 | 146 | ||
@@ -266,6 +259,10 @@ struct pvr2_hdw { | |||
266 | unsigned int freqSelector; /* 0=radio 1=television */ | 259 | unsigned int freqSelector; /* 0=radio 1=television */ |
267 | int freqDirty; | 260 | int freqDirty; |
268 | 261 | ||
262 | /* Current tuner info - this information is polled from the I2C bus */ | ||
263 | struct v4l2_tuner tuner_signal_info; | ||
264 | int tuner_signal_stale; | ||
265 | |||
269 | /* Video standard handling */ | 266 | /* Video standard handling */ |
270 | v4l2_std_id std_mask_eeprom; // Hardware supported selections | 267 | v4l2_std_id std_mask_eeprom; // Hardware supported selections |
271 | v4l2_std_id std_mask_avail; // Which standards we may select from | 268 | v4l2_std_id std_mask_avail; // Which standards we may select from |
@@ -297,11 +294,6 @@ struct pvr2_hdw { | |||
297 | 294 | ||
298 | enum pvr2_config config; | 295 | enum pvr2_config config; |
299 | 296 | ||
300 | /* Information about what audio signal we're hearing */ | ||
301 | int flag_stereo; | ||
302 | int flag_bilingual; | ||
303 | struct pvr2_audio_stat *audio_stat; | ||
304 | |||
305 | /* Control state needed for cx2341x module */ | 297 | /* Control state needed for cx2341x module */ |
306 | struct cx2341x_mpeg_params enc_cur_state; | 298 | struct cx2341x_mpeg_params enc_cur_state; |
307 | struct cx2341x_mpeg_params enc_ctl_state; | 299 | struct cx2341x_mpeg_params enc_ctl_state; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 2de595112224..4672199ae92d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -264,7 +264,6 @@ static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); | |||
264 | static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); | 264 | static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); |
265 | static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); | 265 | static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); |
266 | static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); | 266 | static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); |
267 | static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw); | ||
268 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); | 267 | static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); |
269 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); | 268 | static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); |
270 | static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw); | 269 | static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw); |
@@ -623,8 +622,34 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) | |||
623 | 622 | ||
624 | static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) | 623 | static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) |
625 | { | 624 | { |
626 | *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & | 625 | struct pvr2_hdw *hdw = cptr->hdw; |
627 | PVR2_SIGNAL_OK) ? 1 : 0); | 626 | pvr2_i2c_core_status_poll(hdw); |
627 | *vp = hdw->tuner_signal_info.signal; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) | ||
632 | { | ||
633 | int val = 0; | ||
634 | unsigned int subchan; | ||
635 | struct pvr2_hdw *hdw = cptr->hdw; | ||
636 | if (hdw->tuner_signal_stale) { | ||
637 | pvr2_i2c_core_status_poll(hdw); | ||
638 | } | ||
639 | subchan = hdw->tuner_signal_info.rxsubchans; | ||
640 | if (subchan & V4L2_TUNER_SUB_MONO) { | ||
641 | val |= (1 << V4L2_TUNER_MODE_MONO); | ||
642 | } | ||
643 | if (subchan & V4L2_TUNER_SUB_STEREO) { | ||
644 | val |= (1 << V4L2_TUNER_MODE_STEREO); | ||
645 | } | ||
646 | if (subchan & V4L2_TUNER_SUB_LANG1) { | ||
647 | val |= (1 << V4L2_TUNER_MODE_LANG1); | ||
648 | } | ||
649 | if (subchan & V4L2_TUNER_SUB_LANG2) { | ||
650 | val |= (1 << V4L2_TUNER_MODE_LANG2); | ||
651 | } | ||
652 | *vp = val; | ||
628 | return 0; | 653 | return 0; |
629 | } | 654 | } |
630 | 655 | ||
@@ -898,7 +923,20 @@ static const struct pvr2_ctl_info control_defs[] = { | |||
898 | .desc = "Signal Present", | 923 | .desc = "Signal Present", |
899 | .name = "signal_present", | 924 | .name = "signal_present", |
900 | .get_value = ctrl_signal_get, | 925 | .get_value = ctrl_signal_get, |
901 | DEFBOOL, | 926 | DEFINT(0,65535), |
927 | },{ | ||
928 | .desc = "Audio Modes Present", | ||
929 | .name = "audio_modes_present", | ||
930 | .get_value = ctrl_audio_modes_present_get, | ||
931 | /* For this type we "borrow" the V4L2_TUNER_MODE enum from | ||
932 | v4l. Nothing outside of this module cares about this, | ||
933 | but I reuse it in order to also reuse the | ||
934 | control_values_audiomode string table. */ | ||
935 | DEFMASK(((1 << V4L2_TUNER_MODE_MONO)| | ||
936 | (1 << V4L2_TUNER_MODE_STEREO)| | ||
937 | (1 << V4L2_TUNER_MODE_LANG1)| | ||
938 | (1 << V4L2_TUNER_MODE_LANG2)), | ||
939 | control_values_audiomode), | ||
902 | },{ | 940 | },{ |
903 | .desc = "Video Standards Available Mask", | 941 | .desc = "Video Standards Available Mask", |
904 | .name = "video_standard_mask_available", | 942 | .name = "video_standard_mask_available", |
@@ -1957,6 +1995,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
1957 | hdw,pvr2_device_names[hdw_type]); | 1995 | hdw,pvr2_device_names[hdw_type]); |
1958 | if (!hdw) goto fail; | 1996 | if (!hdw) goto fail; |
1959 | memset(hdw,0,sizeof(*hdw)); | 1997 | memset(hdw,0,sizeof(*hdw)); |
1998 | hdw->tuner_signal_stale = !0; | ||
1960 | cx2341x_fill_defaults(&hdw->enc_ctl_state); | 1999 | cx2341x_fill_defaults(&hdw->enc_ctl_state); |
1961 | 2000 | ||
1962 | hdw->control_cnt = CTRLDEF_COUNT; | 2001 | hdw->control_cnt = CTRLDEF_COUNT; |
@@ -2179,9 +2218,6 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | |||
2179 | pvr2_stream_destroy(hdw->vid_stream); | 2218 | pvr2_stream_destroy(hdw->vid_stream); |
2180 | hdw->vid_stream = NULL; | 2219 | hdw->vid_stream = NULL; |
2181 | } | 2220 | } |
2182 | if (hdw->audio_stat) { | ||
2183 | hdw->audio_stat->detach(hdw->audio_stat->ctxt); | ||
2184 | } | ||
2185 | if (hdw->decoder_ctrl) { | 2221 | if (hdw->decoder_ctrl) { |
2186 | hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); | 2222 | hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); |
2187 | } | 2223 | } |
@@ -2547,34 +2583,6 @@ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) | |||
2547 | } | 2583 | } |
2548 | 2584 | ||
2549 | 2585 | ||
2550 | /* Return bit mask indicating signal status */ | ||
2551 | static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) | ||
2552 | { | ||
2553 | unsigned int msk = 0; | ||
2554 | switch (hdw->input_val) { | ||
2555 | case PVR2_CVAL_INPUT_TV: | ||
2556 | case PVR2_CVAL_INPUT_RADIO: | ||
2557 | if (hdw->decoder_ctrl && | ||
2558 | hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) { | ||
2559 | msk |= PVR2_SIGNAL_OK; | ||
2560 | if (hdw->audio_stat && | ||
2561 | hdw->audio_stat->status(hdw->audio_stat->ctxt)) { | ||
2562 | if (hdw->flag_stereo) { | ||
2563 | msk |= PVR2_SIGNAL_STEREO; | ||
2564 | } | ||
2565 | if (hdw->flag_bilingual) { | ||
2566 | msk |= PVR2_SIGNAL_SAP; | ||
2567 | } | ||
2568 | } | ||
2569 | } | ||
2570 | break; | ||
2571 | default: | ||
2572 | msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO; | ||
2573 | } | ||
2574 | return msk; | ||
2575 | } | ||
2576 | |||
2577 | |||
2578 | int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) | 2586 | int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) |
2579 | { | 2587 | { |
2580 | int result; | 2588 | int result; |
@@ -2590,14 +2598,25 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) | |||
2590 | } | 2598 | } |
2591 | 2599 | ||
2592 | 2600 | ||
2593 | /* Return bit mask indicating signal status */ | 2601 | /* Execute poll of tuner status */ |
2594 | unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw) | 2602 | void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) |
2595 | { | 2603 | { |
2596 | unsigned int msk = 0; | ||
2597 | LOCK_TAKE(hdw->big_lock); do { | 2604 | LOCK_TAKE(hdw->big_lock); do { |
2598 | msk = pvr2_hdw_get_signal_status_internal(hdw); | 2605 | pvr2_i2c_core_status_poll(hdw); |
2599 | } while (0); LOCK_GIVE(hdw->big_lock); | 2606 | } while (0); LOCK_GIVE(hdw->big_lock); |
2600 | return msk; | 2607 | } |
2608 | |||
2609 | |||
2610 | /* Return information about the tuner */ | ||
2611 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) | ||
2612 | { | ||
2613 | LOCK_TAKE(hdw->big_lock); do { | ||
2614 | if (hdw->tuner_signal_stale) { | ||
2615 | pvr2_i2c_core_status_poll(hdw); | ||
2616 | } | ||
2617 | memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); | ||
2618 | } while (0); LOCK_GIVE(hdw->big_lock); | ||
2619 | return 0; | ||
2601 | } | 2620 | } |
2602 | 2621 | ||
2603 | 2622 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index d803f24cc9e0..dc7a3ba8dd18 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -44,12 +44,6 @@ | |||
44 | #define PVR2_CVAL_INPUT_COMPOSITE 2 | 44 | #define PVR2_CVAL_INPUT_COMPOSITE 2 |
45 | #define PVR2_CVAL_INPUT_RADIO 3 | 45 | #define PVR2_CVAL_INPUT_RADIO 3 |
46 | 46 | ||
47 | /* Values that pvr2_hdw_get_signal_status() returns */ | ||
48 | #define PVR2_SIGNAL_OK 0x0001 | ||
49 | #define PVR2_SIGNAL_STEREO 0x0002 | ||
50 | #define PVR2_SIGNAL_SAP 0x0004 | ||
51 | |||
52 | |||
53 | /* Subsystem definitions - these are various pieces that can be | 47 | /* Subsystem definitions - these are various pieces that can be |
54 | independently stopped / started. Usually you don't want to mess with | 48 | independently stopped / started. Usually you don't want to mess with |
55 | this directly (let the driver handle things itself), but it is useful | 49 | this directly (let the driver handle things itself), but it is useful |
@@ -155,8 +149,11 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *); | |||
155 | /* Return name for this driver instance */ | 149 | /* Return name for this driver instance */ |
156 | const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); | 150 | const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); |
157 | 151 | ||
158 | /* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */ | 152 | /* Mark tuner status stale so that it will be re-fetched */ |
159 | unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *); | 153 | void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *); |
154 | |||
155 | /* Return information about the tuner */ | ||
156 | int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *); | ||
160 | 157 | ||
161 | /* Query device and see if it thinks it is on a high-speed USB link */ | 158 | /* Query device and see if it thinks it is on a high-speed USB link */ |
162 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); | 159 | int pvr2_hdw_is_hsm(struct pvr2_hdw *); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c index 05121666b9ba..16fa075a1eec 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c | |||
@@ -59,6 +59,7 @@ void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | |||
59 | (1 << OP_FREQ) | | 59 | (1 << OP_FREQ) | |
60 | (1 << OP_SIZE) | | 60 | (1 << OP_SIZE) | |
61 | (1 << OP_LOG)); | 61 | (1 << OP_LOG)); |
62 | cp->status_poll = pvr2_v4l2_cmd_status_poll; | ||
62 | 63 | ||
63 | if (id == I2C_DRIVERID_MSP3400) { | 64 | if (id == I2C_DRIVERID_MSP3400) { |
64 | if (pvr2_i2c_msp3400_setup(hdw,cp)) { | 65 | if (pvr2_i2c_msp3400_setup(hdw,cp)) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c index 51da8945efe4..b1f6809625e8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c | |||
@@ -37,6 +37,7 @@ static void set_standard(struct pvr2_hdw *hdw) | |||
37 | vs = hdw->std_mask_cur; | 37 | vs = hdw->std_mask_cur; |
38 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | 38 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); |
39 | } | 39 | } |
40 | hdw->tuner_signal_stale = !0; | ||
40 | } | 41 | } |
41 | 42 | ||
42 | 43 | ||
@@ -145,13 +146,21 @@ static void set_frequency(struct pvr2_hdw *hdw) | |||
145 | struct v4l2_frequency freq; | 146 | struct v4l2_frequency freq; |
146 | fv = pvr2_hdw_get_cur_freq(hdw); | 147 | fv = pvr2_hdw_get_cur_freq(hdw); |
147 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); | 148 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); |
149 | if (hdw->tuner_signal_stale) { | ||
150 | pvr2_i2c_core_status_poll(hdw); | ||
151 | } | ||
148 | memset(&freq,0,sizeof(freq)); | 152 | memset(&freq,0,sizeof(freq)); |
149 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | 153 | if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { |
150 | // ((fv * 1000) / 62500) | 154 | // ((fv * 1000) / 62500) |
151 | freq.frequency = (fv * 2) / 125; | 155 | freq.frequency = (fv * 2) / 125; |
152 | freq.type = V4L2_TUNER_RADIO; | ||
153 | } else { | 156 | } else { |
154 | freq.frequency = fv / 62500; | 157 | freq.frequency = fv / 62500; |
158 | } | ||
159 | /* tuner-core currently doesn't seem to care about this, but | ||
160 | let's set it anyway for completeness. */ | ||
161 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
162 | freq.type = V4L2_TUNER_RADIO; | ||
163 | } else { | ||
155 | freq.type = V4L2_TUNER_ANALOG_TV; | 164 | freq.type = V4L2_TUNER_ANALOG_TV; |
156 | } | 165 | } |
157 | freq.tuner = 0; | 166 | freq.tuner = 0; |
@@ -230,6 +239,12 @@ void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) | |||
230 | } | 239 | } |
231 | 240 | ||
232 | 241 | ||
242 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) | ||
243 | { | ||
244 | pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&cp->hdw->tuner_signal_info); | ||
245 | } | ||
246 | |||
247 | |||
233 | /* | 248 | /* |
234 | Stuff for Emacs to see, in order to encourage consistent editing style: | 249 | Stuff for Emacs to see, in order to encourage consistent editing style: |
235 | *** Local Variables: *** | 250 | *** Local Variables: *** |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h index 894de610893b..6a9bb46d0654 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h | |||
@@ -34,6 +34,7 @@ extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; | |||
34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; | 34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; |
35 | 35 | ||
36 | void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); | 36 | void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); |
37 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); | ||
37 | 38 | ||
38 | #endif /* __PVRUSB2_CMD_V4L2_H */ | 39 | #endif /* __PVRUSB2_CMD_V4L2_H */ |
39 | 40 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index 62a7cfca837d..35a06652a60c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -590,6 +590,27 @@ static int handler_check(struct pvr2_i2c_client *cp) | |||
590 | 590 | ||
591 | #define BUFSIZE 500 | 591 | #define BUFSIZE 500 |
592 | 592 | ||
593 | |||
594 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) | ||
595 | { | ||
596 | struct list_head *item; | ||
597 | struct pvr2_i2c_client *cp; | ||
598 | mutex_lock(&hdw->i2c_list_lock); do { | ||
599 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; | ||
600 | memset(vtp,0,sizeof(vtp)); | ||
601 | list_for_each(item,&hdw->i2c_clients) { | ||
602 | cp = list_entry(item,struct pvr2_i2c_client,list); | ||
603 | if (!cp->detected_flag) continue; | ||
604 | if (!cp->status_poll) continue; | ||
605 | cp->status_poll(cp); | ||
606 | } | ||
607 | hdw->tuner_signal_stale = 0; | ||
608 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
609 | } | ||
610 | |||
611 | |||
612 | /* Issue various I2C operations to bring chip-level drivers into sync with | ||
613 | state stored in this driver. */ | ||
593 | void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | 614 | void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) |
594 | { | 615 | { |
595 | unsigned long msk; | 616 | unsigned long msk; |
@@ -876,6 +897,7 @@ static int pvr2_i2c_attach_inform(struct i2c_client *client) | |||
876 | client->addr,cp); | 897 | client->addr,cp); |
877 | if (!cp) return -ENOMEM; | 898 | if (!cp) return -ENOMEM; |
878 | memset(cp,0,sizeof(*cp)); | 899 | memset(cp,0,sizeof(*cp)); |
900 | cp->hdw = hdw; | ||
879 | INIT_LIST_HEAD(&cp->list); | 901 | INIT_LIST_HEAD(&cp->list); |
880 | cp->client = client; | 902 | cp->client = client; |
881 | mutex_lock(&hdw->i2c_list_lock); do { | 903 | mutex_lock(&hdw->i2c_list_lock); do { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h index 6d7e25247576..bd0807b905bb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h | |||
@@ -35,10 +35,12 @@ struct pvr2_i2c_client { | |||
35 | struct i2c_client *client; | 35 | struct i2c_client *client; |
36 | struct pvr2_i2c_handler *handler; | 36 | struct pvr2_i2c_handler *handler; |
37 | struct list_head list; | 37 | struct list_head list; |
38 | struct pvr2_hdw *hdw; | ||
38 | int detected_flag; | 39 | int detected_flag; |
39 | int recv_enable; | 40 | int recv_enable; |
40 | unsigned long pend_mask; | 41 | unsigned long pend_mask; |
41 | unsigned long ctl_mask; | 42 | unsigned long ctl_mask; |
43 | void (*status_poll)(struct pvr2_i2c_client *); | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct pvr2_i2c_handler { | 46 | struct pvr2_i2c_handler { |
@@ -67,6 +69,7 @@ int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); | |||
67 | 69 | ||
68 | int pvr2_i2c_core_check_stale(struct pvr2_hdw *); | 70 | int pvr2_i2c_core_check_stale(struct pvr2_hdw *); |
69 | void pvr2_i2c_core_sync(struct pvr2_hdw *); | 71 | void pvr2_i2c_core_sync(struct pvr2_hdw *); |
72 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *); | ||
70 | unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); | 73 | unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); |
71 | #define PVR2_I2C_DETAIL_DEBUG 0x0001 | 74 | #define PVR2_I2C_DETAIL_DEBUG 0x0001 |
72 | #define PVR2_I2C_DETAIL_HANDLER 0x0002 | 75 | #define PVR2_I2C_DETAIL_HANDLER 0x0002 |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 655a722289ed..2a6763865266 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -95,25 +95,6 @@ static struct v4l2_capability pvr_capability ={ | |||
95 | .reserved = {0,0,0,0} | 95 | .reserved = {0,0,0,0} |
96 | }; | 96 | }; |
97 | 97 | ||
98 | static struct v4l2_tuner pvr_v4l2_tuners[]= { | ||
99 | { | ||
100 | .index = 0, | ||
101 | .name = "TV Tuner", | ||
102 | .type = V4L2_TUNER_ANALOG_TV, | ||
103 | .capability = (V4L2_TUNER_CAP_NORM | | ||
104 | V4L2_TUNER_CAP_STEREO | | ||
105 | V4L2_TUNER_CAP_LANG1 | | ||
106 | V4L2_TUNER_CAP_LANG2), | ||
107 | .rangelow = 0, | ||
108 | .rangehigh = 0, | ||
109 | .rxsubchans = V4L2_TUNER_SUB_STEREO, | ||
110 | .audmode = V4L2_TUNER_MODE_STEREO, | ||
111 | .signal = 0, | ||
112 | .afc = 0, | ||
113 | .reserved = {0,0,0,0} | ||
114 | } | ||
115 | }; | ||
116 | |||
117 | static struct v4l2_fmtdesc pvr_fmtdesc [] = { | 98 | static struct v4l2_fmtdesc pvr_fmtdesc [] = { |
118 | { | 99 | { |
119 | .index = 0, | 100 | .index = 0, |
@@ -358,34 +339,8 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
358 | case VIDIOC_G_TUNER: | 339 | case VIDIOC_G_TUNER: |
359 | { | 340 | { |
360 | struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; | 341 | struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; |
361 | unsigned int status_mask; | 342 | pvr2_hdw_execute_tuner_poll(hdw); |
362 | int val; | 343 | ret = pvr2_hdw_get_tuner_status(hdw,vt); |
363 | if (vt->index !=0) break; | ||
364 | |||
365 | status_mask = pvr2_hdw_get_signal_status(hdw); | ||
366 | |||
367 | memcpy(vt, &pvr_v4l2_tuners[vt->index], | ||
368 | sizeof(struct v4l2_tuner)); | ||
369 | |||
370 | vt->signal = 0; | ||
371 | if (status_mask & PVR2_SIGNAL_OK) { | ||
372 | if (status_mask & PVR2_SIGNAL_STEREO) { | ||
373 | vt->rxsubchans = V4L2_TUNER_SUB_STEREO; | ||
374 | } else { | ||
375 | vt->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
376 | } | ||
377 | if (status_mask & PVR2_SIGNAL_SAP) { | ||
378 | vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 | | ||
379 | V4L2_TUNER_SUB_LANG2); | ||
380 | } | ||
381 | vt->signal = 65535; | ||
382 | } | ||
383 | |||
384 | val = 0; | ||
385 | ret = pvr2_ctrl_get_value( | ||
386 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), | ||
387 | &val); | ||
388 | vt->audmode = val; | ||
389 | break; | 344 | break; |
390 | } | 345 | } |
391 | 346 | ||
@@ -405,8 +360,27 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
405 | { | 360 | { |
406 | const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; | 361 | const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; |
407 | unsigned long fv; | 362 | unsigned long fv; |
408 | fv = vf->frequency; | 363 | struct v4l2_tuner vt; |
364 | int cur_input; | ||
365 | struct pvr2_ctrl *ctrlp; | ||
366 | ret = pvr2_hdw_get_tuner_status(hdw,&vt); | ||
367 | if (ret != 0) break; | ||
368 | ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); | ||
369 | ret = pvr2_ctrl_get_value(ctrlp,&cur_input); | ||
370 | if (ret != 0) break; | ||
409 | if (vf->type == V4L2_TUNER_RADIO) { | 371 | if (vf->type == V4L2_TUNER_RADIO) { |
372 | if (cur_input != PVR2_CVAL_INPUT_RADIO) { | ||
373 | pvr2_ctrl_set_value(ctrlp, | ||
374 | PVR2_CVAL_INPUT_RADIO); | ||
375 | } | ||
376 | } else { | ||
377 | if (cur_input == PVR2_CVAL_INPUT_RADIO) { | ||
378 | pvr2_ctrl_set_value(ctrlp, | ||
379 | PVR2_CVAL_INPUT_TV); | ||
380 | } | ||
381 | } | ||
382 | fv = vf->frequency; | ||
383 | if (vt.capability & V4L2_TUNER_CAP_LOW) { | ||
410 | fv = (fv * 125) / 2; | 384 | fv = (fv * 125) / 2; |
411 | } else { | 385 | } else { |
412 | fv = fv * 62500; | 386 | fv = fv * 62500; |
@@ -420,7 +394,10 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
420 | { | 394 | { |
421 | struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; | 395 | struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; |
422 | int val = 0; | 396 | int val = 0; |
423 | int cur_input = PVR2_CVAL_INPUT_TV; | 397 | int cur_input; |
398 | struct v4l2_tuner vt; | ||
399 | ret = pvr2_hdw_get_tuner_status(hdw,&vt); | ||
400 | if (ret != 0) break; | ||
424 | ret = pvr2_ctrl_get_value( | 401 | ret = pvr2_ctrl_get_value( |
425 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), | 402 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), |
426 | &val); | 403 | &val); |
@@ -429,14 +406,16 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
429 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), | 406 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), |
430 | &cur_input); | 407 | &cur_input); |
431 | if (cur_input == PVR2_CVAL_INPUT_RADIO) { | 408 | if (cur_input == PVR2_CVAL_INPUT_RADIO) { |
432 | val = (val * 2) / 125; | ||
433 | vf->frequency = val; | ||
434 | vf->type = V4L2_TUNER_RADIO; | 409 | vf->type = V4L2_TUNER_RADIO; |
435 | } else { | 410 | } else { |
436 | val /= 62500; | ||
437 | vf->frequency = val; | ||
438 | vf->type = V4L2_TUNER_ANALOG_TV; | 411 | vf->type = V4L2_TUNER_ANALOG_TV; |
439 | } | 412 | } |
413 | if (vt.capability & V4L2_TUNER_CAP_LOW) { | ||
414 | val = (val * 2) / 125; | ||
415 | } else { | ||
416 | val /= 62500; | ||
417 | } | ||
418 | vf->frequency = val; | ||
440 | break; | 419 | break; |
441 | } | 420 | } |
442 | 421 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 2a826464911a..8b37748cfcba 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | |||
@@ -183,18 +183,6 @@ static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) | |||
183 | } | 183 | } |
184 | 184 | ||
185 | 185 | ||
186 | static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt) | ||
187 | { | ||
188 | struct v4l2_tuner vt; | ||
189 | int ret; | ||
190 | |||
191 | memset(&vt,0,sizeof(vt)); | ||
192 | ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); | ||
193 | if (ret < 0) return -EINVAL; | ||
194 | return vt.signal ? 1 : 0; | ||
195 | } | ||
196 | |||
197 | |||
198 | static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) | 186 | static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) |
199 | { | 187 | { |
200 | return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); | 188 | return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); |
@@ -227,7 +215,6 @@ int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, | |||
227 | ctxt->ctrl.ctxt = ctxt; | 215 | ctxt->ctrl.ctxt = ctxt; |
228 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; | 216 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; |
229 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; | 217 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; |
230 | ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; | ||
231 | ctxt->client = cp; | 218 | ctxt->client = cp; |
232 | ctxt->hdw = hdw; | 219 | ctxt->hdw = hdw; |
233 | ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ | 220 | ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ |