diff options
Diffstat (limited to 'drivers/media/video/pvrusb2')
30 files changed, 904 insertions, 1957 deletions
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 854c2a885358..f9b6001e1dd7 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig | |||
@@ -40,10 +40,10 @@ config VIDEO_PVRUSB2_DVB | |||
40 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 40 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
41 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 41 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
42 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 42 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
43 | select DVB_TDA10048 if !DVB_FE_CUSTOMIZE | 43 | select DVB_TDA10048 if !DVB_FE_CUSTOMISE |
44 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE | 44 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE |
45 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE | 45 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE |
46 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE | 46 | select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE |
47 | ---help--- | 47 | ---help--- |
48 | 48 | ||
49 | This option enables a DVB interface for the pvrusb2 driver. | 49 | This option enables a DVB interface for the pvrusb2 driver. |
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile index 4fda2de69ab7..de2fc14f043b 100644 --- a/drivers/media/video/pvrusb2/Makefile +++ b/drivers/media/video/pvrusb2/Makefile | |||
@@ -2,14 +2,15 @@ obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o | |||
2 | obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o | 2 | obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o |
3 | obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o | 3 | obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o |
4 | 4 | ||
5 | pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ | 5 | pvrusb2-objs := pvrusb2-i2c-core.o \ |
6 | pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ | 6 | pvrusb2-audio.o \ |
7 | pvrusb2-encoder.o pvrusb2-video-v4l.o \ | 7 | pvrusb2-encoder.o pvrusb2-video-v4l.o \ |
8 | pvrusb2-eeprom.o pvrusb2-tuner.o \ | 8 | pvrusb2-eeprom.o \ |
9 | pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ | 9 | pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ |
10 | pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ | 10 | pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \ |
11 | pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ | 11 | pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ |
12 | pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ | 12 | pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \ |
13 | pvrusb2-cs53l32a.o \ | ||
13 | $(obj-pvrusb2-dvb-y) \ | 14 | $(obj-pvrusb2-dvb-y) \ |
14 | $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) | 15 | $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) |
15 | 16 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index cdedaa55f152..ccf2a3c7ad06 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c | |||
@@ -26,14 +26,6 @@ | |||
26 | #include <media/msp3400.h> | 26 | #include <media/msp3400.h> |
27 | #include <media/v4l2-common.h> | 27 | #include <media/v4l2-common.h> |
28 | 28 | ||
29 | struct pvr2_msp3400_handler { | ||
30 | struct pvr2_hdw *hdw; | ||
31 | struct pvr2_i2c_client *client; | ||
32 | struct pvr2_i2c_handler i2c_handler; | ||
33 | unsigned long stale_mask; | ||
34 | }; | ||
35 | |||
36 | |||
37 | 29 | ||
38 | struct routing_scheme { | 30 | struct routing_scheme { |
39 | const int *def; | 31 | const int *def; |
@@ -63,123 +55,33 @@ static const struct routing_scheme routing_schemes[] = { | |||
63 | }, | 55 | }, |
64 | }; | 56 | }; |
65 | 57 | ||
66 | /* This function selects the correct audio input source */ | 58 | void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
67 | static void set_stereo(struct pvr2_msp3400_handler *ctxt) | ||
68 | { | ||
69 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
70 | struct v4l2_routing route; | ||
71 | const struct routing_scheme *sp; | ||
72 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | ||
73 | |||
74 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); | ||
75 | |||
76 | if ((sid < ARRAY_SIZE(routing_schemes)) && | ||
77 | ((sp = routing_schemes + sid) != NULL) && | ||
78 | (hdw->input_val >= 0) && | ||
79 | (hdw->input_val < sp->cnt)) { | ||
80 | route.input = sp->def[hdw->input_val]; | ||
81 | } else { | ||
82 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
83 | "*** WARNING *** i2c msp3400 v4l2 set_stereo:" | ||
84 | " Invalid routing scheme (%u) and/or input (%d)", | ||
85 | sid,hdw->input_val); | ||
86 | return; | ||
87 | } | ||
88 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); | ||
89 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); | ||
90 | } | ||
91 | |||
92 | |||
93 | static int check_stereo(struct pvr2_msp3400_handler *ctxt) | ||
94 | { | 59 | { |
95 | struct pvr2_hdw *hdw = ctxt->hdw; | 60 | if (hdw->input_dirty || hdw->force_dirty) { |
96 | return hdw->input_dirty; | 61 | struct v4l2_routing route; |
97 | } | 62 | const struct routing_scheme *sp; |
98 | 63 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | |
99 | 64 | ||
100 | struct pvr2_msp3400_ops { | 65 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); |
101 | void (*update)(struct pvr2_msp3400_handler *); | 66 | |
102 | int (*check)(struct pvr2_msp3400_handler *); | 67 | if ((sid < ARRAY_SIZE(routing_schemes)) && |
103 | }; | 68 | ((sp = routing_schemes + sid) != NULL) && |
104 | 69 | (hdw->input_val >= 0) && | |
105 | 70 | (hdw->input_val < sp->cnt)) { | |
106 | static const struct pvr2_msp3400_ops msp3400_ops[] = { | 71 | route.input = sp->def[hdw->input_val]; |
107 | { .update = set_stereo, .check = check_stereo}, | 72 | } else { |
108 | }; | 73 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
109 | 74 | "*** WARNING *** subdev msp3400 set_input:" | |
110 | 75 | " Invalid routing scheme (%u)" | |
111 | static int msp3400_check(struct pvr2_msp3400_handler *ctxt) | 76 | " and/or input (%d)", |
112 | { | 77 | sid, hdw->input_val); |
113 | unsigned long msk; | 78 | return; |
114 | unsigned int idx; | ||
115 | |||
116 | for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { | ||
117 | msk = 1 << idx; | ||
118 | if (ctxt->stale_mask & msk) continue; | ||
119 | if (msp3400_ops[idx].check(ctxt)) { | ||
120 | ctxt->stale_mask |= msk; | ||
121 | } | 79 | } |
80 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); | ||
81 | sd->ops->audio->s_routing(sd, &route); | ||
122 | } | 82 | } |
123 | return ctxt->stale_mask != 0; | ||
124 | } | 83 | } |
125 | 84 | ||
126 | |||
127 | static void msp3400_update(struct pvr2_msp3400_handler *ctxt) | ||
128 | { | ||
129 | unsigned long msk; | ||
130 | unsigned int idx; | ||
131 | |||
132 | for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { | ||
133 | msk = 1 << idx; | ||
134 | if (!(ctxt->stale_mask & msk)) continue; | ||
135 | ctxt->stale_mask &= ~msk; | ||
136 | msp3400_ops[idx].update(ctxt); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | |||
141 | static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) | ||
142 | { | ||
143 | ctxt->client->handler = NULL; | ||
144 | kfree(ctxt); | ||
145 | } | ||
146 | |||
147 | |||
148 | static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt, | ||
149 | char *buf,unsigned int cnt) | ||
150 | { | ||
151 | return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2"); | ||
152 | } | ||
153 | |||
154 | |||
155 | static const struct pvr2_i2c_handler_functions msp3400_funcs = { | ||
156 | .detach = (void (*)(void *))pvr2_msp3400_detach, | ||
157 | .check = (int (*)(void *))msp3400_check, | ||
158 | .update = (void (*)(void *))msp3400_update, | ||
159 | .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe, | ||
160 | }; | ||
161 | |||
162 | |||
163 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | ||
164 | { | ||
165 | struct pvr2_msp3400_handler *ctxt; | ||
166 | if (cp->handler) return 0; | ||
167 | |||
168 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); | ||
169 | if (!ctxt) return 0; | ||
170 | |||
171 | ctxt->i2c_handler.func_data = ctxt; | ||
172 | ctxt->i2c_handler.func_table = &msp3400_funcs; | ||
173 | ctxt->client = cp; | ||
174 | ctxt->hdw = hdw; | ||
175 | ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1; | ||
176 | cp->handler = &ctxt->i2c_handler; | ||
177 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", | ||
178 | cp->client->addr); | ||
179 | return !0; | ||
180 | } | ||
181 | |||
182 | |||
183 | /* | 85 | /* |
184 | Stuff for Emacs to see, in order to encourage consistent editing style: | 86 | Stuff for Emacs to see, in order to encourage consistent editing style: |
185 | *** Local Variables: *** | 87 | *** Local Variables: *** |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h index ac54eed3721b..e3e63d750891 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.h +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h | |||
@@ -22,10 +22,8 @@ | |||
22 | #ifndef __PVRUSB2_AUDIO_H | 22 | #ifndef __PVRUSB2_AUDIO_H |
23 | #define __PVRUSB2_AUDIO_H | 23 | #define __PVRUSB2_AUDIO_H |
24 | 24 | ||
25 | #include "pvrusb2-i2c-core.h" | 25 | #include "pvrusb2-hdw-internal.h" |
26 | 26 | void pvr2_msp3400_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); | |
27 | int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); | ||
28 | |||
29 | #endif /* __PVRUSB2_AUDIO_H */ | 27 | #endif /* __PVRUSB2_AUDIO_H */ |
30 | 28 | ||
31 | /* | 29 | /* |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c new file mode 100644 index 000000000000..b5c3428ebb9f --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | ||
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | |||
24 | This source file is specifically designed to interface with the | ||
25 | v4l-dvb cs53l32a module. | ||
26 | |||
27 | */ | ||
28 | |||
29 | #include "pvrusb2-cs53l32a.h" | ||
30 | |||
31 | |||
32 | #include "pvrusb2-hdw-internal.h" | ||
33 | #include "pvrusb2-debug.h" | ||
34 | #include <linux/videodev2.h> | ||
35 | #include <media/v4l2-common.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/slab.h> | ||
38 | |||
39 | struct routing_scheme { | ||
40 | const int *def; | ||
41 | unsigned int cnt; | ||
42 | }; | ||
43 | |||
44 | |||
45 | static const int routing_scheme1[] = { | ||
46 | [PVR2_CVAL_INPUT_TV] = 2, /* 1 or 2 seems to work here */ | ||
47 | [PVR2_CVAL_INPUT_RADIO] = 2, | ||
48 | [PVR2_CVAL_INPUT_COMPOSITE] = 0, | ||
49 | [PVR2_CVAL_INPUT_SVIDEO] = 0, | ||
50 | }; | ||
51 | |||
52 | static const struct routing_scheme routing_schemes[] = { | ||
53 | [PVR2_ROUTING_SCHEME_ONAIR] = { | ||
54 | .def = routing_scheme1, | ||
55 | .cnt = ARRAY_SIZE(routing_scheme1), | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | |||
60 | void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | ||
61 | { | ||
62 | if (hdw->input_dirty || hdw->force_dirty) { | ||
63 | struct v4l2_routing route; | ||
64 | const struct routing_scheme *sp; | ||
65 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | ||
66 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", | ||
67 | hdw->input_val); | ||
68 | if ((sid < ARRAY_SIZE(routing_schemes)) && | ||
69 | ((sp = routing_schemes + sid) != NULL) && | ||
70 | (hdw->input_val >= 0) && | ||
71 | (hdw->input_val < sp->cnt)) { | ||
72 | route.input = sp->def[hdw->input_val]; | ||
73 | } else { | ||
74 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
75 | "*** WARNING *** subdev v4l2 set_input:" | ||
76 | " Invalid routing scheme (%u)" | ||
77 | " and/or input (%d)", | ||
78 | sid, hdw->input_val); | ||
79 | return; | ||
80 | } | ||
81 | route.output = 0; | ||
82 | sd->ops->audio->s_routing(sd, &route); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | |||
87 | /* | ||
88 | Stuff for Emacs to see, in order to encourage consistent editing style: | ||
89 | *** Local Variables: *** | ||
90 | *** mode: c *** | ||
91 | *** fill-column: 70 *** | ||
92 | *** tab-width: 8 *** | ||
93 | *** c-basic-offset: 8 *** | ||
94 | *** End: *** | ||
95 | */ | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h index ef4afaf37b0a..53ba548b72a7 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.h +++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | 4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> |
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -17,14 +18,24 @@ | |||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | * | 19 | * |
19 | */ | 20 | */ |
20 | #ifndef __PVRUSB2_TUNER_H | ||
21 | #define __PVRUSB2_TUNER_H | ||
22 | 21 | ||
23 | #include "pvrusb2-i2c-core.h" | 22 | #ifndef __PVRUSB2_CS53L32A_H |
23 | #define __PVRUSB2_CS53L32A_H | ||
24 | 24 | ||
25 | int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); | 25 | /* |
26 | |||
27 | This module connects the pvrusb2 driver to the I2C chip level | ||
28 | driver which handles device video processing. This interface is | ||
29 | used internally by the driver; higher level code should only | ||
30 | interact through the interface provided by pvrusb2-hdw.h. | ||
31 | |||
32 | */ | ||
33 | |||
34 | |||
35 | #include "pvrusb2-hdw-internal.h" | ||
36 | void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); | ||
26 | 37 | ||
27 | #endif /* __PVRUSB2_TUNER_H */ | 38 | #endif /* __PVRUSB2_AUDIO_CS53L32A_H */ |
28 | 39 | ||
29 | /* | 40 | /* |
30 | Stuff for Emacs to see, in order to encourage consistent editing style: | 41 | Stuff for Emacs to see, in order to encourage consistent editing style: |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 895859ec495a..4e017ff26c36 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | #include "pvrusb2-cx2584x-v4l.h" | 29 | #include "pvrusb2-cx2584x-v4l.h" |
30 | #include "pvrusb2-video-v4l.h" | 30 | #include "pvrusb2-video-v4l.h" |
31 | #include "pvrusb2-i2c-cmd-v4l2.h" | ||
32 | 31 | ||
33 | 32 | ||
34 | #include "pvrusb2-hdw-internal.h" | 33 | #include "pvrusb2-hdw-internal.h" |
@@ -39,14 +38,6 @@ | |||
39 | #include <linux/errno.h> | 38 | #include <linux/errno.h> |
40 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
41 | 40 | ||
42 | struct pvr2_v4l_cx2584x { | ||
43 | struct pvr2_i2c_handler handler; | ||
44 | struct pvr2_decoder_ctrl ctrl; | ||
45 | struct pvr2_i2c_client *client; | ||
46 | struct pvr2_hdw *hdw; | ||
47 | unsigned long stale_mask; | ||
48 | }; | ||
49 | |||
50 | 41 | ||
51 | struct routing_scheme_item { | 42 | struct routing_scheme_item { |
52 | int vid; | 43 | int vid; |
@@ -110,218 +101,44 @@ static const struct routing_scheme routing_schemes[] = { | |||
110 | }, | 101 | }, |
111 | }; | 102 | }; |
112 | 103 | ||
113 | static void set_input(struct pvr2_v4l_cx2584x *ctxt) | 104 | void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
114 | { | ||
115 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
116 | struct v4l2_routing route; | ||
117 | enum cx25840_video_input vid_input; | ||
118 | enum cx25840_audio_input aud_input; | ||
119 | const struct routing_scheme *sp; | ||
120 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | ||
121 | |||
122 | memset(&route,0,sizeof(route)); | ||
123 | |||
124 | if ((sid < ARRAY_SIZE(routing_schemes)) && | ||
125 | ((sp = routing_schemes + sid) != NULL) && | ||
126 | (hdw->input_val >= 0) && | ||
127 | (hdw->input_val < sp->cnt)) { | ||
128 | vid_input = sp->def[hdw->input_val].vid; | ||
129 | aud_input = sp->def[hdw->input_val].aud; | ||
130 | } else { | ||
131 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
132 | "*** WARNING *** i2c cx2584x set_input:" | ||
133 | " Invalid routing scheme (%u) and/or input (%d)", | ||
134 | sid,hdw->input_val); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x", | ||
139 | vid_input,aud_input); | ||
140 | route.input = (u32)vid_input; | ||
141 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
142 | route.input = (u32)aud_input; | ||
143 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); | ||
144 | } | ||
145 | |||
146 | |||
147 | static int check_input(struct pvr2_v4l_cx2584x *ctxt) | ||
148 | { | ||
149 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
150 | return hdw->input_dirty != 0; | ||
151 | } | ||
152 | |||
153 | |||
154 | static void set_audio(struct pvr2_v4l_cx2584x *ctxt) | ||
155 | { | ||
156 | u32 val; | ||
157 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
158 | |||
159 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d", | ||
160 | hdw->srate_val); | ||
161 | switch (hdw->srate_val) { | ||
162 | default: | ||
163 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: | ||
164 | val = 48000; | ||
165 | break; | ||
166 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: | ||
167 | val = 44100; | ||
168 | break; | ||
169 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: | ||
170 | val = 32000; | ||
171 | break; | ||
172 | } | ||
173 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); | ||
174 | } | ||
175 | |||
176 | |||
177 | static int check_audio(struct pvr2_v4l_cx2584x *ctxt) | ||
178 | { | ||
179 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
180 | return hdw->srate_dirty != 0; | ||
181 | } | ||
182 | |||
183 | |||
184 | struct pvr2_v4l_cx2584x_ops { | ||
185 | void (*update)(struct pvr2_v4l_cx2584x *); | ||
186 | int (*check)(struct pvr2_v4l_cx2584x *); | ||
187 | }; | ||
188 | |||
189 | |||
190 | static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = { | ||
191 | { .update = set_input, .check = check_input}, | ||
192 | { .update = set_audio, .check = check_audio}, | ||
193 | }; | ||
194 | |||
195 | |||
196 | static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt) | ||
197 | { | 105 | { |
198 | ctxt->client->handler = NULL; | 106 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update..."); |
199 | pvr2_hdw_set_decoder(ctxt->hdw,NULL); | 107 | if (hdw->input_dirty || hdw->force_dirty) { |
200 | kfree(ctxt); | 108 | struct v4l2_routing route; |
201 | } | 109 | enum cx25840_video_input vid_input; |
202 | 110 | enum cx25840_audio_input aud_input; | |
203 | 111 | const struct routing_scheme *sp; | |
204 | static int decoder_check(struct pvr2_v4l_cx2584x *ctxt) | 112 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; |
205 | { | 113 | |
206 | unsigned long msk; | 114 | memset(&route, 0, sizeof(route)); |
207 | unsigned int idx; | 115 | |
208 | 116 | if ((sid < ARRAY_SIZE(routing_schemes)) && | |
209 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { | 117 | ((sp = routing_schemes + sid) != NULL) && |
210 | msk = 1 << idx; | 118 | (hdw->input_val >= 0) && |
211 | if (ctxt->stale_mask & msk) continue; | 119 | (hdw->input_val < sp->cnt)) { |
212 | if (decoder_ops[idx].check(ctxt)) { | 120 | vid_input = sp->def[hdw->input_val].vid; |
213 | ctxt->stale_mask |= msk; | 121 | aud_input = sp->def[hdw->input_val].aud; |
122 | } else { | ||
123 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
124 | "*** WARNING *** subdev cx2584x set_input:" | ||
125 | " Invalid routing scheme (%u)" | ||
126 | " and/or input (%d)", | ||
127 | sid, hdw->input_val); | ||
128 | return; | ||
214 | } | 129 | } |
215 | } | ||
216 | return ctxt->stale_mask != 0; | ||
217 | } | ||
218 | |||
219 | 130 | ||
220 | static void decoder_update(struct pvr2_v4l_cx2584x *ctxt) | 131 | pvr2_trace(PVR2_TRACE_CHIPS, |
221 | { | 132 | "subdev cx2584x set_input vid=0x%x aud=0x%x", |
222 | unsigned long msk; | 133 | vid_input, aud_input); |
223 | unsigned int idx; | 134 | route.input = (u32)vid_input; |
224 | 135 | sd->ops->video->s_routing(sd, &route); | |
225 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { | 136 | route.input = (u32)aud_input; |
226 | msk = 1 << idx; | 137 | sd->ops->audio->s_routing(sd, &route); |
227 | if (!(ctxt->stale_mask & msk)) continue; | ||
228 | ctxt->stale_mask &= ~msk; | ||
229 | decoder_ops[idx].update(ctxt); | ||
230 | } | 138 | } |
231 | } | 139 | } |
232 | 140 | ||
233 | 141 | ||
234 | static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl) | ||
235 | { | ||
236 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl); | ||
237 | pvr2_v4l2_cmd_stream(ctxt->client,fl); | ||
238 | } | ||
239 | |||
240 | |||
241 | static int decoder_detect(struct pvr2_i2c_client *cp) | ||
242 | { | ||
243 | int ret; | ||
244 | /* Attempt to query the decoder - let's see if it will answer */ | ||
245 | struct v4l2_queryctrl qc; | ||
246 | |||
247 | memset(&qc,0,sizeof(qc)); | ||
248 | |||
249 | qc.id = V4L2_CID_BRIGHTNESS; | ||
250 | |||
251 | ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc); | ||
252 | return ret == 0; /* Return true if it answered */ | ||
253 | } | ||
254 | |||
255 | |||
256 | static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, | ||
257 | char *buf,unsigned int cnt) | ||
258 | { | ||
259 | return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l"); | ||
260 | } | ||
261 | |||
262 | |||
263 | static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt) | ||
264 | { | ||
265 | int ret; | ||
266 | ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL); | ||
267 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret); | ||
268 | } | ||
269 | |||
270 | |||
271 | static const struct pvr2_i2c_handler_functions hfuncs = { | ||
272 | .detach = (void (*)(void *))decoder_detach, | ||
273 | .check = (int (*)(void *))decoder_check, | ||
274 | .update = (void (*)(void *))decoder_update, | ||
275 | .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, | ||
276 | }; | ||
277 | |||
278 | |||
279 | int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, | ||
280 | struct pvr2_i2c_client *cp) | ||
281 | { | ||
282 | struct pvr2_v4l_cx2584x *ctxt; | ||
283 | |||
284 | if (hdw->decoder_ctrl) return 0; | ||
285 | if (cp->handler) return 0; | ||
286 | if (!decoder_detect(cp)) return 0; | ||
287 | |||
288 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); | ||
289 | if (!ctxt) return 0; | ||
290 | |||
291 | ctxt->handler.func_data = ctxt; | ||
292 | ctxt->handler.func_table = &hfuncs; | ||
293 | ctxt->ctrl.ctxt = ctxt; | ||
294 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; | ||
295 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; | ||
296 | ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; | ||
297 | ctxt->client = cp; | ||
298 | ctxt->hdw = hdw; | ||
299 | ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; | ||
300 | pvr2_hdw_set_decoder(hdw,&ctxt->ctrl); | ||
301 | cp->handler = &ctxt->handler; | ||
302 | { | ||
303 | /* | ||
304 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit | ||
305 | of nuttiness for cx25840 causes that module to | ||
306 | correctly set up its video scaling. This is really | ||
307 | a problem in the cx25840 module itself, but we work | ||
308 | around it here. The problem has not been seen in | ||
309 | ivtv because there VBI is supported and set up. We | ||
310 | don't do VBI here (at least not yet) and thus we | ||
311 | never attempted to even set it up. | ||
312 | */ | ||
313 | struct v4l2_format fmt; | ||
314 | memset(&fmt,0,sizeof(fmt)); | ||
315 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
316 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt); | ||
317 | } | ||
318 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", | ||
319 | cp->client->addr); | ||
320 | return !0; | ||
321 | } | ||
322 | |||
323 | |||
324 | |||
325 | 142 | ||
326 | /* | 143 | /* |
327 | Stuff for Emacs to see, in order to encourage consistent editing style: | 144 | Stuff for Emacs to see, in order to encourage consistent editing style: |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h index 66abf77f51fd..e35c2322a08c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h | |||
@@ -34,9 +34,9 @@ | |||
34 | 34 | ||
35 | 35 | ||
36 | 36 | ||
37 | #include "pvrusb2-i2c-core.h" | 37 | #include "pvrusb2-hdw-internal.h" |
38 | 38 | ||
39 | int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); | 39 | void pvr2_cx25840_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); |
40 | 40 | ||
41 | 41 | ||
42 | #endif /* __PVRUSB2_CX2584X_V4L_H */ | 42 | #endif /* __PVRUSB2_CX2584X_V4L_H */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c index ca892fb78a5b..fbe3856bdca6 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "pvrusb2-debugifc.h" | 23 | #include "pvrusb2-debugifc.h" |
24 | #include "pvrusb2-hdw.h" | 24 | #include "pvrusb2-hdw.h" |
25 | #include "pvrusb2-debug.h" | 25 | #include "pvrusb2-debug.h" |
26 | #include "pvrusb2-i2c-core.h" | ||
27 | 26 | ||
28 | struct debugifc_mask_item { | 27 | struct debugifc_mask_item { |
29 | const char *name; | 28 | const char *name; |
@@ -147,10 +146,6 @@ int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) | |||
147 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | 146 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; |
148 | ccnt = pvr2_hdw_state_report(hdw,buf,acnt); | 147 | ccnt = pvr2_hdw_state_report(hdw,buf,acnt); |
149 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | 148 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; |
150 | ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n"); | ||
151 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | ||
152 | ccnt = pvr2_i2c_report(hdw,buf,acnt); | ||
153 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | ||
154 | 149 | ||
155 | return bcnt; | 150 | return bcnt; |
156 | } | 151 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h index e24ff59f8605..2f8d46761cd0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h | |||
@@ -22,16 +22,16 @@ | |||
22 | 22 | ||
23 | struct pvr2_hdw; | 23 | struct pvr2_hdw; |
24 | 24 | ||
25 | /* Non-intrusively print some useful debugging info from inside the | ||
26 | driver. This should work even if the driver appears to be | ||
27 | wedged. */ | ||
28 | int pvr2_debugifc_print_info(struct pvr2_hdw *, | ||
29 | char *buf_ptr,unsigned int buf_size); | ||
30 | |||
31 | /* Print general status of driver. This will also trigger a probe of | 25 | /* Print general status of driver. This will also trigger a probe of |
32 | the USB link. Unlike print_info(), this one synchronizes with the | 26 | the USB link. Unlike print_info(), this one synchronizes with the |
33 | driver so the information should be self-consistent (but it will | 27 | driver so the information should be self-consistent (but it will |
34 | hang if the driver is wedged). */ | 28 | hang if the driver is wedged). */ |
29 | int pvr2_debugifc_print_info(struct pvr2_hdw *, | ||
30 | char *buf_ptr, unsigned int buf_size); | ||
31 | |||
32 | /* Non-intrusively print some useful debugging info from inside the | ||
33 | driver. This should work even if the driver appears to be | ||
34 | wedged. */ | ||
35 | int pvr2_debugifc_print_status(struct pvr2_hdw *, | 35 | int pvr2_debugifc_print_status(struct pvr2_hdw *, |
36 | char *buf_ptr,unsigned int buf_size); | 36 | char *buf_ptr,unsigned int buf_size); |
37 | 37 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index cbe2a3417851..1cb6a260e8b0 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c | |||
@@ -46,10 +46,11 @@ pvr2_device_desc structures. | |||
46 | /*------------------------------------------------------------------------*/ | 46 | /*------------------------------------------------------------------------*/ |
47 | /* Hauppauge PVR-USB2 Model 29xxx */ | 47 | /* Hauppauge PVR-USB2 Model 29xxx */ |
48 | 48 | ||
49 | static const char *pvr2_client_29xxx[] = { | 49 | static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = { |
50 | "msp3400", | 50 | { .module_id = PVR2_CLIENT_ID_SAA7115 }, |
51 | "saa7115", | 51 | { .module_id = PVR2_CLIENT_ID_MSP3400 }, |
52 | "tuner", | 52 | { .module_id = PVR2_CLIENT_ID_TUNER }, |
53 | { .module_id = PVR2_CLIENT_ID_DEMOD }, | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | static const char *pvr2_fw1_names_29xxx[] = { | 56 | static const char *pvr2_fw1_names_29xxx[] = { |
@@ -59,8 +60,8 @@ static const char *pvr2_fw1_names_29xxx[] = { | |||
59 | static const struct pvr2_device_desc pvr2_device_29xxx = { | 60 | static const struct pvr2_device_desc pvr2_device_29xxx = { |
60 | .description = "WinTV PVR USB2 Model Category 29xxx", | 61 | .description = "WinTV PVR USB2 Model Category 29xxx", |
61 | .shortname = "29xxx", | 62 | .shortname = "29xxx", |
62 | .client_modules.lst = pvr2_client_29xxx, | 63 | .client_table.lst = pvr2_cli_29xxx, |
63 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_29xxx), | 64 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx), |
64 | .fx2_firmware.lst = pvr2_fw1_names_29xxx, | 65 | .fx2_firmware.lst = pvr2_fw1_names_29xxx, |
65 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), | 66 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx), |
66 | .flag_has_hauppauge_rom = !0, | 67 | .flag_has_hauppauge_rom = !0, |
@@ -77,10 +78,11 @@ static const struct pvr2_device_desc pvr2_device_29xxx = { | |||
77 | /*------------------------------------------------------------------------*/ | 78 | /*------------------------------------------------------------------------*/ |
78 | /* Hauppauge PVR-USB2 Model 24xxx */ | 79 | /* Hauppauge PVR-USB2 Model 24xxx */ |
79 | 80 | ||
80 | static const char *pvr2_client_24xxx[] = { | 81 | static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = { |
81 | "cx25840", | 82 | { .module_id = PVR2_CLIENT_ID_CX25840 }, |
82 | "tuner", | 83 | { .module_id = PVR2_CLIENT_ID_TUNER }, |
83 | "wm8775", | 84 | { .module_id = PVR2_CLIENT_ID_WM8775 }, |
85 | { .module_id = PVR2_CLIENT_ID_DEMOD }, | ||
84 | }; | 86 | }; |
85 | 87 | ||
86 | static const char *pvr2_fw1_names_24xxx[] = { | 88 | static const char *pvr2_fw1_names_24xxx[] = { |
@@ -90,8 +92,8 @@ static const char *pvr2_fw1_names_24xxx[] = { | |||
90 | static const struct pvr2_device_desc pvr2_device_24xxx = { | 92 | static const struct pvr2_device_desc pvr2_device_24xxx = { |
91 | .description = "WinTV PVR USB2 Model Category 24xxx", | 93 | .description = "WinTV PVR USB2 Model Category 24xxx", |
92 | .shortname = "24xxx", | 94 | .shortname = "24xxx", |
93 | .client_modules.lst = pvr2_client_24xxx, | 95 | .client_table.lst = pvr2_cli_24xxx, |
94 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_24xxx), | 96 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx), |
95 | .fx2_firmware.lst = pvr2_fw1_names_24xxx, | 97 | .fx2_firmware.lst = pvr2_fw1_names_24xxx, |
96 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx), | 98 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx), |
97 | .flag_has_cx25840 = !0, | 99 | .flag_has_cx25840 = !0, |
@@ -111,16 +113,16 @@ static const struct pvr2_device_desc pvr2_device_24xxx = { | |||
111 | /*------------------------------------------------------------------------*/ | 113 | /*------------------------------------------------------------------------*/ |
112 | /* GOTVIEW USB2.0 DVD2 */ | 114 | /* GOTVIEW USB2.0 DVD2 */ |
113 | 115 | ||
114 | static const char *pvr2_client_gotview_2[] = { | 116 | static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = { |
115 | "cx25840", | 117 | { .module_id = PVR2_CLIENT_ID_CX25840 }, |
116 | "tuner", | 118 | { .module_id = PVR2_CLIENT_ID_TUNER }, |
117 | }; | 119 | }; |
118 | 120 | ||
119 | static const struct pvr2_device_desc pvr2_device_gotview_2 = { | 121 | static const struct pvr2_device_desc pvr2_device_gotview_2 = { |
120 | .description = "Gotview USB 2.0 DVD 2", | 122 | .description = "Gotview USB 2.0 DVD 2", |
121 | .shortname = "gv2", | 123 | .shortname = "gv2", |
122 | .client_modules.lst = pvr2_client_gotview_2, | 124 | .client_table.lst = pvr2_cli_gotview_2, |
123 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), | 125 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), |
124 | .flag_has_cx25840 = !0, | 126 | .flag_has_cx25840 = !0, |
125 | .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | 127 | .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
126 | .flag_has_analogtuner = !0, | 128 | .flag_has_analogtuner = !0, |
@@ -140,8 +142,8 @@ static const struct pvr2_device_desc pvr2_device_gotview_2 = { | |||
140 | static const struct pvr2_device_desc pvr2_device_gotview_2d = { | 142 | static const struct pvr2_device_desc pvr2_device_gotview_2d = { |
141 | .description = "Gotview USB 2.0 DVD Deluxe", | 143 | .description = "Gotview USB 2.0 DVD Deluxe", |
142 | .shortname = "gv2d", | 144 | .shortname = "gv2d", |
143 | .client_modules.lst = pvr2_client_gotview_2, | 145 | .client_table.lst = pvr2_cli_gotview_2, |
144 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_gotview_2), | 146 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2), |
145 | .flag_has_cx25840 = !0, | 147 | .flag_has_cx25840 = !0, |
146 | .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, | 148 | .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3, |
147 | .flag_has_analogtuner = !0, | 149 | .flag_has_analogtuner = !0, |
@@ -181,29 +183,29 @@ static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap) | |||
181 | return 0; | 183 | return 0; |
182 | } | 184 | } |
183 | 185 | ||
184 | static struct pvr2_dvb_props pvr2_onair_creator_fe_props = { | 186 | static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = { |
185 | .frontend_attach = pvr2_lgdt3303_attach, | 187 | .frontend_attach = pvr2_lgdt3303_attach, |
186 | .tuner_attach = pvr2_lgh06xf_attach, | 188 | .tuner_attach = pvr2_lgh06xf_attach, |
187 | }; | 189 | }; |
188 | #endif | 190 | #endif |
189 | 191 | ||
190 | static const char *pvr2_client_onair_creator[] = { | 192 | static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = { |
191 | "saa7115", | 193 | { .module_id = PVR2_CLIENT_ID_SAA7115 }, |
192 | "tuner", | 194 | { .module_id = PVR2_CLIENT_ID_CS53L32A }, |
193 | "cs53l32a", | 195 | { .module_id = PVR2_CLIENT_ID_TUNER }, |
194 | }; | 196 | }; |
195 | 197 | ||
196 | static const struct pvr2_device_desc pvr2_device_onair_creator = { | 198 | static const struct pvr2_device_desc pvr2_device_onair_creator = { |
197 | .description = "OnAir Creator Hybrid USB tuner", | 199 | .description = "OnAir Creator Hybrid USB tuner", |
198 | .shortname = "oac", | 200 | .shortname = "oac", |
199 | .client_modules.lst = pvr2_client_onair_creator, | 201 | .client_table.lst = pvr2_cli_onair_creator, |
200 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_creator), | 202 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator), |
201 | .default_tuner_type = TUNER_LG_TDVS_H06XF, | 203 | .default_tuner_type = TUNER_LG_TDVS_H06XF, |
202 | .flag_has_analogtuner = !0, | 204 | .flag_has_analogtuner = !0, |
203 | .flag_has_composite = !0, | 205 | .flag_has_composite = !0, |
204 | .flag_has_svideo = !0, | 206 | .flag_has_svideo = !0, |
205 | .flag_digital_requires_cx23416 = !0, | 207 | .flag_digital_requires_cx23416 = !0, |
206 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, | 208 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, |
207 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, | 209 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, |
208 | .default_std_mask = V4L2_STD_NTSC_M, | 210 | .default_std_mask = V4L2_STD_NTSC_M, |
209 | #ifdef CONFIG_VIDEO_PVRUSB2_DVB | 211 | #ifdef CONFIG_VIDEO_PVRUSB2_DVB |
@@ -241,29 +243,29 @@ static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap) | |||
241 | return 0; | 243 | return 0; |
242 | } | 244 | } |
243 | 245 | ||
244 | static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { | 246 | static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { |
245 | .frontend_attach = pvr2_lgdt3302_attach, | 247 | .frontend_attach = pvr2_lgdt3302_attach, |
246 | .tuner_attach = pvr2_fcv1236d_attach, | 248 | .tuner_attach = pvr2_fcv1236d_attach, |
247 | }; | 249 | }; |
248 | #endif | 250 | #endif |
249 | 251 | ||
250 | static const char *pvr2_client_onair_usb2[] = { | 252 | static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = { |
251 | "saa7115", | 253 | { .module_id = PVR2_CLIENT_ID_SAA7115 }, |
252 | "tuner", | 254 | { .module_id = PVR2_CLIENT_ID_CS53L32A }, |
253 | "cs53l32a", | 255 | { .module_id = PVR2_CLIENT_ID_TUNER }, |
254 | }; | 256 | }; |
255 | 257 | ||
256 | static const struct pvr2_device_desc pvr2_device_onair_usb2 = { | 258 | static const struct pvr2_device_desc pvr2_device_onair_usb2 = { |
257 | .description = "OnAir USB2 Hybrid USB tuner", | 259 | .description = "OnAir USB2 Hybrid USB tuner", |
258 | .shortname = "oa2", | 260 | .shortname = "oa2", |
259 | .client_modules.lst = pvr2_client_onair_usb2, | 261 | .client_table.lst = pvr2_cli_onair_usb2, |
260 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_onair_usb2), | 262 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2), |
261 | .default_tuner_type = TUNER_PHILIPS_FCV1236D, | 263 | .default_tuner_type = TUNER_PHILIPS_FCV1236D, |
262 | .flag_has_analogtuner = !0, | 264 | .flag_has_analogtuner = !0, |
263 | .flag_has_composite = !0, | 265 | .flag_has_composite = !0, |
264 | .flag_has_svideo = !0, | 266 | .flag_has_svideo = !0, |
265 | .flag_digital_requires_cx23416 = !0, | 267 | .flag_digital_requires_cx23416 = !0, |
266 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE, | 268 | .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR, |
267 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, | 269 | .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR, |
268 | .default_std_mask = V4L2_STD_NTSC_M, | 270 | .default_std_mask = V4L2_STD_NTSC_M, |
269 | #ifdef CONFIG_VIDEO_PVRUSB2_DVB | 271 | #ifdef CONFIG_VIDEO_PVRUSB2_DVB |
@@ -314,15 +316,16 @@ static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) | |||
314 | return 0; | 316 | return 0; |
315 | } | 317 | } |
316 | 318 | ||
317 | static struct pvr2_dvb_props pvr2_73xxx_dvb_props = { | 319 | static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = { |
318 | .frontend_attach = pvr2_tda10048_attach, | 320 | .frontend_attach = pvr2_tda10048_attach, |
319 | .tuner_attach = pvr2_73xxx_tda18271_8295_attach, | 321 | .tuner_attach = pvr2_73xxx_tda18271_8295_attach, |
320 | }; | 322 | }; |
321 | #endif | 323 | #endif |
322 | 324 | ||
323 | static const char *pvr2_client_73xxx[] = { | 325 | static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = { |
324 | "cx25840", | 326 | { .module_id = PVR2_CLIENT_ID_CX25840 }, |
325 | "tuner", | 327 | { .module_id = PVR2_CLIENT_ID_TUNER, |
328 | .i2c_address_list = "\x42"}, | ||
326 | }; | 329 | }; |
327 | 330 | ||
328 | static const char *pvr2_fw1_names_73xxx[] = { | 331 | static const char *pvr2_fw1_names_73xxx[] = { |
@@ -332,8 +335,8 @@ static const char *pvr2_fw1_names_73xxx[] = { | |||
332 | static const struct pvr2_device_desc pvr2_device_73xxx = { | 335 | static const struct pvr2_device_desc pvr2_device_73xxx = { |
333 | .description = "WinTV HVR-1900 Model Category 73xxx", | 336 | .description = "WinTV HVR-1900 Model Category 73xxx", |
334 | .shortname = "73xxx", | 337 | .shortname = "73xxx", |
335 | .client_modules.lst = pvr2_client_73xxx, | 338 | .client_table.lst = pvr2_cli_73xxx, |
336 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_73xxx), | 339 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), |
337 | .fx2_firmware.lst = pvr2_fw1_names_73xxx, | 340 | .fx2_firmware.lst = pvr2_fw1_names_73xxx, |
338 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx), | 341 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx), |
339 | .flag_has_cx25840 = !0, | 342 | .flag_has_cx25840 = !0, |
@@ -418,22 +421,17 @@ static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap) | |||
418 | return 0; | 421 | return 0; |
419 | } | 422 | } |
420 | 423 | ||
421 | static struct pvr2_dvb_props pvr2_750xx_dvb_props = { | 424 | static const struct pvr2_dvb_props pvr2_750xx_dvb_props = { |
422 | .frontend_attach = pvr2_s5h1409_attach, | 425 | .frontend_attach = pvr2_s5h1409_attach, |
423 | .tuner_attach = pvr2_tda18271_8295_attach, | 426 | .tuner_attach = pvr2_tda18271_8295_attach, |
424 | }; | 427 | }; |
425 | 428 | ||
426 | static struct pvr2_dvb_props pvr2_751xx_dvb_props = { | 429 | static const struct pvr2_dvb_props pvr2_751xx_dvb_props = { |
427 | .frontend_attach = pvr2_s5h1411_attach, | 430 | .frontend_attach = pvr2_s5h1411_attach, |
428 | .tuner_attach = pvr2_tda18271_8295_attach, | 431 | .tuner_attach = pvr2_tda18271_8295_attach, |
429 | }; | 432 | }; |
430 | #endif | 433 | #endif |
431 | 434 | ||
432 | static const char *pvr2_client_75xxx[] = { | ||
433 | "cx25840", | ||
434 | "tuner", | ||
435 | }; | ||
436 | |||
437 | static const char *pvr2_fw1_names_75xxx[] = { | 435 | static const char *pvr2_fw1_names_75xxx[] = { |
438 | "v4l-pvrusb2-73xxx-01.fw", | 436 | "v4l-pvrusb2-73xxx-01.fw", |
439 | }; | 437 | }; |
@@ -441,8 +439,8 @@ static const char *pvr2_fw1_names_75xxx[] = { | |||
441 | static const struct pvr2_device_desc pvr2_device_750xx = { | 439 | static const struct pvr2_device_desc pvr2_device_750xx = { |
442 | .description = "WinTV HVR-1950 Model Category 750xx", | 440 | .description = "WinTV HVR-1950 Model Category 750xx", |
443 | .shortname = "750xx", | 441 | .shortname = "750xx", |
444 | .client_modules.lst = pvr2_client_75xxx, | 442 | .client_table.lst = pvr2_cli_73xxx, |
445 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), | 443 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), |
446 | .fx2_firmware.lst = pvr2_fw1_names_75xxx, | 444 | .fx2_firmware.lst = pvr2_fw1_names_75xxx, |
447 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), | 445 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), |
448 | .flag_has_cx25840 = !0, | 446 | .flag_has_cx25840 = !0, |
@@ -463,8 +461,8 @@ static const struct pvr2_device_desc pvr2_device_750xx = { | |||
463 | static const struct pvr2_device_desc pvr2_device_751xx = { | 461 | static const struct pvr2_device_desc pvr2_device_751xx = { |
464 | .description = "WinTV HVR-1950 Model Category 751xx", | 462 | .description = "WinTV HVR-1950 Model Category 751xx", |
465 | .shortname = "751xx", | 463 | .shortname = "751xx", |
466 | .client_modules.lst = pvr2_client_75xxx, | 464 | .client_table.lst = pvr2_cli_73xxx, |
467 | .client_modules.cnt = ARRAY_SIZE(pvr2_client_75xxx), | 465 | .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx), |
468 | .fx2_firmware.lst = pvr2_fw1_names_75xxx, | 466 | .fx2_firmware.lst = pvr2_fw1_names_75xxx, |
469 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), | 467 | .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx), |
470 | .flag_has_cx25840 = !0, | 468 | .flag_has_cx25840 = !0, |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h index cb3a33eb0276..3e553389cbc3 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h | |||
@@ -33,6 +33,34 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | 35 | ||
36 | #define PVR2_CLIENT_ID_NULL 0 | ||
37 | #define PVR2_CLIENT_ID_MSP3400 1 | ||
38 | #define PVR2_CLIENT_ID_CX25840 2 | ||
39 | #define PVR2_CLIENT_ID_SAA7115 3 | ||
40 | #define PVR2_CLIENT_ID_TUNER 4 | ||
41 | #define PVR2_CLIENT_ID_CS53L32A 5 | ||
42 | #define PVR2_CLIENT_ID_WM8775 6 | ||
43 | #define PVR2_CLIENT_ID_DEMOD 7 | ||
44 | |||
45 | struct pvr2_device_client_desc { | ||
46 | /* One ovr PVR2_CLIENT_ID_xxxx */ | ||
47 | unsigned char module_id; | ||
48 | |||
49 | /* Null-terminated array of I2C addresses to try in order | ||
50 | initialize the module. It's safe to make this null terminated | ||
51 | since we're never going to encounter an i2c device with an | ||
52 | address of zero. If this is a null pointer or zero-length, | ||
53 | then no I2C addresses have been specified, in which case we'll | ||
54 | try some compiled in defaults for now. */ | ||
55 | unsigned char *i2c_address_list; | ||
56 | }; | ||
57 | |||
58 | struct pvr2_device_client_table { | ||
59 | const struct pvr2_device_client_desc *lst; | ||
60 | unsigned char cnt; | ||
61 | }; | ||
62 | |||
63 | |||
36 | struct pvr2_string_table { | 64 | struct pvr2_string_table { |
37 | const char **lst; | 65 | const char **lst; |
38 | unsigned int cnt; | 66 | unsigned int cnt; |
@@ -40,6 +68,7 @@ struct pvr2_string_table { | |||
40 | 68 | ||
41 | #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 | 69 | #define PVR2_ROUTING_SCHEME_HAUPPAUGE 0 |
42 | #define PVR2_ROUTING_SCHEME_GOTVIEW 1 | 70 | #define PVR2_ROUTING_SCHEME_GOTVIEW 1 |
71 | #define PVR2_ROUTING_SCHEME_ONAIR 2 | ||
43 | 72 | ||
44 | #define PVR2_DIGITAL_SCHEME_NONE 0 | 73 | #define PVR2_DIGITAL_SCHEME_NONE 0 |
45 | #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 | 74 | #define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1 |
@@ -66,6 +95,9 @@ struct pvr2_device_desc { | |||
66 | /* List of additional client modules we need to load */ | 95 | /* List of additional client modules we need to load */ |
67 | struct pvr2_string_table client_modules; | 96 | struct pvr2_string_table client_modules; |
68 | 97 | ||
98 | /* List of defined client modules we need to load */ | ||
99 | struct pvr2_device_client_table client_table; | ||
100 | |||
69 | /* List of FX2 firmware file names we should search; if empty then | 101 | /* List of FX2 firmware file names we should search; if empty then |
70 | FX2 firmware check / load is skipped and we assume the device | 102 | FX2 firmware check / load is skipped and we assume the device |
71 | was initialized from internal ROM. */ | 103 | was initialized from internal ROM. */ |
@@ -73,7 +105,7 @@ struct pvr2_device_desc { | |||
73 | 105 | ||
74 | #ifdef CONFIG_VIDEO_PVRUSB2_DVB | 106 | #ifdef CONFIG_VIDEO_PVRUSB2_DVB |
75 | /* callback functions to handle attachment of digital tuner & demod */ | 107 | /* callback functions to handle attachment of digital tuner & demod */ |
76 | struct pvr2_dvb_props *dvb_props; | 108 | const struct pvr2_dvb_props *dvb_props; |
77 | 109 | ||
78 | #endif | 110 | #endif |
79 | /* Initial standard bits to use for this device, if not zero. | 111 | /* Initial standard bits to use for this device, if not zero. |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c index 77b3c3385066..b7f5c49b1dbc 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-dvb.c +++ b/drivers/media/video/pvrusb2/pvrusb2-dvb.c | |||
@@ -321,7 +321,7 @@ static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap) | |||
321 | static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) | 321 | static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap) |
322 | { | 322 | { |
323 | struct pvr2_hdw *hdw = adap->channel.hdw; | 323 | struct pvr2_hdw *hdw = adap->channel.hdw; |
324 | struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; | 324 | const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props; |
325 | int ret = 0; | 325 | int ret = 0; |
326 | 326 | ||
327 | if (dvb_props == NULL) { | 327 | if (dvb_props == NULL) { |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c index 273d2a1aa220..54ac5349dee2 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c | |||
@@ -347,7 +347,7 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) | |||
347 | int encMisc3Arg = 0; | 347 | int encMisc3Arg = 0; |
348 | 348 | ||
349 | #if 0 | 349 | #if 0 |
350 | /* This inexplicable bit happens in the Hauppage windows | 350 | /* This inexplicable bit happens in the Hauppauge windows |
351 | driver (for both 24xxx and 29xxx devices). However I | 351 | driver (for both 24xxx and 29xxx devices). However I |
352 | currently see no difference in behavior with or without | 352 | currently see no difference in behavior with or without |
353 | this stuff. Leave this here as a note of its existence, | 353 | this stuff. Leave this here as a note of its existence, |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h index de7ee7264be6..5d75eb5211b1 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
39 | #include "pvrusb2-hdw.h" | 39 | #include "pvrusb2-hdw.h" |
40 | #include "pvrusb2-io.h" | 40 | #include "pvrusb2-io.h" |
41 | #include <media/v4l2-device.h> | ||
41 | #include <media/cx2341x.h> | 42 | #include <media/cx2341x.h> |
42 | #include "pvrusb2-devattr.h" | 43 | #include "pvrusb2-devattr.h" |
43 | 44 | ||
@@ -57,8 +58,6 @@ | |||
57 | #define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0) | 58 | #define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0) |
58 | #define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0) | 59 | #define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0) |
59 | 60 | ||
60 | struct pvr2_decoder; | ||
61 | |||
62 | typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); | 61 | typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); |
63 | typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); | 62 | typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); |
64 | typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int); | 63 | typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int); |
@@ -139,22 +138,6 @@ struct pvr2_ctrl { | |||
139 | }; | 138 | }; |
140 | 139 | ||
141 | 140 | ||
142 | struct pvr2_decoder_ctrl { | ||
143 | void *ctxt; | ||
144 | void (*detach)(void *); | ||
145 | void (*enable)(void *,int); | ||
146 | void (*force_reset)(void *); | ||
147 | }; | ||
148 | |||
149 | #define PVR2_I2C_PEND_DETECT 0x01 /* Need to detect a client type */ | ||
150 | #define PVR2_I2C_PEND_CLIENT 0x02 /* Client needs a specific update */ | ||
151 | #define PVR2_I2C_PEND_REFRESH 0x04 /* Client has specific pending bits */ | ||
152 | #define PVR2_I2C_PEND_STALE 0x08 /* Broadcast pending bits */ | ||
153 | |||
154 | #define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\ | ||
155 | PVR2_I2C_PEND_CLIENT |\ | ||
156 | PVR2_I2C_PEND_REFRESH |\ | ||
157 | PVR2_I2C_PEND_STALE) | ||
158 | 141 | ||
159 | /* Disposition of firmware1 loading situation */ | 142 | /* Disposition of firmware1 loading situation */ |
160 | #define FW1_STATE_UNKNOWN 0 | 143 | #define FW1_STATE_UNKNOWN 0 |
@@ -179,6 +162,8 @@ struct pvr2_hdw { | |||
179 | struct usb_device *usb_dev; | 162 | struct usb_device *usb_dev; |
180 | struct usb_interface *usb_intf; | 163 | struct usb_interface *usb_intf; |
181 | 164 | ||
165 | /* Our handle into the v4l2 sub-device architecture */ | ||
166 | struct v4l2_device v4l2_dev; | ||
182 | /* Device description, anything that must adjust behavior based on | 167 | /* Device description, anything that must adjust behavior based on |
183 | device specific info will use information held here. */ | 168 | device specific info will use information held here. */ |
184 | const struct pvr2_device_desc *hdw_desc; | 169 | const struct pvr2_device_desc *hdw_desc; |
@@ -186,7 +171,6 @@ struct pvr2_hdw { | |||
186 | /* Kernel worker thread handling */ | 171 | /* Kernel worker thread handling */ |
187 | struct workqueue_struct *workqueue; | 172 | struct workqueue_struct *workqueue; |
188 | struct work_struct workpoll; /* Update driver state */ | 173 | struct work_struct workpoll; /* Update driver state */ |
189 | struct work_struct worki2csync; /* Update i2c clients */ | ||
190 | 174 | ||
191 | /* Video spigot */ | 175 | /* Video spigot */ |
192 | struct pvr2_stream *vid_stream; | 176 | struct pvr2_stream *vid_stream; |
@@ -195,20 +179,26 @@ struct pvr2_hdw { | |||
195 | struct mutex big_lock_mutex; | 179 | struct mutex big_lock_mutex; |
196 | int big_lock_held; /* For debugging */ | 180 | int big_lock_held; /* For debugging */ |
197 | 181 | ||
182 | /* This is a simple string which identifies the instance of this | ||
183 | driver. It is unique within the set of existing devices, but | ||
184 | there is no attempt to keep the name consistent with the same | ||
185 | physical device each time. */ | ||
198 | char name[32]; | 186 | char name[32]; |
199 | 187 | ||
188 | /* This is a simple string which identifies the physical device | ||
189 | instance itself - if possible. (If not possible, then it is | ||
190 | based on the specific driver instance, similar to name above.) | ||
191 | The idea here is that userspace might hopefully be able to use | ||
192 | this recognize specific tuners. It will encode a serial number, | ||
193 | if available. */ | ||
194 | char identifier[32]; | ||
195 | |||
200 | /* I2C stuff */ | 196 | /* I2C stuff */ |
201 | struct i2c_adapter i2c_adap; | 197 | struct i2c_adapter i2c_adap; |
202 | struct i2c_algorithm i2c_algo; | 198 | struct i2c_algorithm i2c_algo; |
203 | pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT]; | 199 | pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT]; |
204 | int i2c_cx25840_hack_state; | 200 | int i2c_cx25840_hack_state; |
205 | int i2c_linked; | 201 | int i2c_linked; |
206 | unsigned int i2c_pend_types; /* Which types of update are needed */ | ||
207 | unsigned long i2c_pend_mask; /* Change bits we need to scan */ | ||
208 | unsigned long i2c_stale_mask; /* Pending broadcast change bits */ | ||
209 | unsigned long i2c_active_mask; /* All change bits currently in use */ | ||
210 | struct list_head i2c_clients; | ||
211 | struct mutex i2c_list_lock; | ||
212 | 202 | ||
213 | /* Frequency table */ | 203 | /* Frequency table */ |
214 | unsigned int freqTable[FREQTABLE_SIZE]; | 204 | unsigned int freqTable[FREQTABLE_SIZE]; |
@@ -275,6 +265,7 @@ struct pvr2_hdw { | |||
275 | wait_queue_head_t state_wait_data; | 265 | wait_queue_head_t state_wait_data; |
276 | 266 | ||
277 | 267 | ||
268 | int force_dirty; /* consider all controls dirty if true */ | ||
278 | int flag_ok; /* device in known good state */ | 269 | int flag_ok; /* device in known good state */ |
279 | int flag_disconnected; /* flag_ok == 0 due to disconnect */ | 270 | int flag_disconnected; /* flag_ok == 0 due to disconnect */ |
280 | int flag_init_ok; /* true if structure is fully initialized */ | 271 | int flag_init_ok; /* true if structure is fully initialized */ |
@@ -283,17 +274,13 @@ struct pvr2_hdw { | |||
283 | int flag_decoder_missed;/* We've noticed missing decoder */ | 274 | int flag_decoder_missed;/* We've noticed missing decoder */ |
284 | int flag_tripped; /* Indicates overall failure to start */ | 275 | int flag_tripped; /* Indicates overall failure to start */ |
285 | 276 | ||
286 | struct pvr2_decoder_ctrl *decoder_ctrl; | 277 | unsigned int decoder_client_id; |
287 | 278 | ||
288 | // CPU firmware info (used to help find / save firmware data) | 279 | // CPU firmware info (used to help find / save firmware data) |
289 | char *fw_buffer; | 280 | char *fw_buffer; |
290 | unsigned int fw_size; | 281 | unsigned int fw_size; |
291 | int fw_cpu_flag; /* True if we are dealing with the CPU */ | 282 | int fw_cpu_flag; /* True if we are dealing with the CPU */ |
292 | 283 | ||
293 | // True if there is a request to trigger logging of state in each | ||
294 | // module. | ||
295 | int log_requested; | ||
296 | |||
297 | /* Tuner / frequency control stuff */ | 284 | /* Tuner / frequency control stuff */ |
298 | unsigned int tuner_type; | 285 | unsigned int tuner_type; |
299 | int tuner_updated; | 286 | int tuner_updated; |
@@ -391,7 +378,8 @@ struct pvr2_hdw { | |||
391 | 378 | ||
392 | /* This function gets the current frequency */ | 379 | /* This function gets the current frequency */ |
393 | unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); | 380 | unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *); |
394 | void pvr2_hdw_set_decoder(struct pvr2_hdw *,struct pvr2_decoder_ctrl *); | 381 | |
382 | void pvr2_hdw_status_poll(struct pvr2_hdw *); | ||
395 | 383 | ||
396 | #endif /* __PVRUSB2_HDW_INTERNAL_H */ | 384 | #endif /* __PVRUSB2_HDW_INTERNAL_H */ |
397 | 385 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index fa304e5f252a..7a65b42a4f53 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -24,17 +24,22 @@ | |||
24 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
25 | #include <linux/videodev2.h> | 25 | #include <linux/videodev2.h> |
26 | #include <media/v4l2-common.h> | 26 | #include <media/v4l2-common.h> |
27 | #include <media/tuner.h> | ||
27 | #include "pvrusb2.h" | 28 | #include "pvrusb2.h" |
28 | #include "pvrusb2-std.h" | 29 | #include "pvrusb2-std.h" |
29 | #include "pvrusb2-util.h" | 30 | #include "pvrusb2-util.h" |
30 | #include "pvrusb2-hdw.h" | 31 | #include "pvrusb2-hdw.h" |
31 | #include "pvrusb2-i2c-core.h" | 32 | #include "pvrusb2-i2c-core.h" |
32 | #include "pvrusb2-tuner.h" | ||
33 | #include "pvrusb2-eeprom.h" | 33 | #include "pvrusb2-eeprom.h" |
34 | #include "pvrusb2-hdw-internal.h" | 34 | #include "pvrusb2-hdw-internal.h" |
35 | #include "pvrusb2-encoder.h" | 35 | #include "pvrusb2-encoder.h" |
36 | #include "pvrusb2-debug.h" | 36 | #include "pvrusb2-debug.h" |
37 | #include "pvrusb2-fx2-cmd.h" | 37 | #include "pvrusb2-fx2-cmd.h" |
38 | #include "pvrusb2-wm8775.h" | ||
39 | #include "pvrusb2-video-v4l.h" | ||
40 | #include "pvrusb2-cx2584x-v4l.h" | ||
41 | #include "pvrusb2-cs53l32a.h" | ||
42 | #include "pvrusb2-audio.h" | ||
38 | 43 | ||
39 | #define TV_MIN_FREQ 55250000L | 44 | #define TV_MIN_FREQ 55250000L |
40 | #define TV_MAX_FREQ 850000000L | 45 | #define TV_MAX_FREQ 850000000L |
@@ -104,6 +109,39 @@ MODULE_PARM_DESC(radio_freq, "specify initial radio frequency"); | |||
104 | /* size of a firmware chunk */ | 109 | /* size of a firmware chunk */ |
105 | #define FIRMWARE_CHUNK_SIZE 0x2000 | 110 | #define FIRMWARE_CHUNK_SIZE 0x2000 |
106 | 111 | ||
112 | typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *, | ||
113 | struct v4l2_subdev *); | ||
114 | |||
115 | static const pvr2_subdev_update_func pvr2_module_update_functions[] = { | ||
116 | [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update, | ||
117 | [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update, | ||
118 | [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update, | ||
119 | [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update, | ||
120 | [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update, | ||
121 | }; | ||
122 | |||
123 | static const char *module_names[] = { | ||
124 | [PVR2_CLIENT_ID_MSP3400] = "msp3400", | ||
125 | [PVR2_CLIENT_ID_CX25840] = "cx25840", | ||
126 | [PVR2_CLIENT_ID_SAA7115] = "saa7115", | ||
127 | [PVR2_CLIENT_ID_TUNER] = "tuner", | ||
128 | [PVR2_CLIENT_ID_DEMOD] = "tuner", | ||
129 | [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a", | ||
130 | [PVR2_CLIENT_ID_WM8775] = "wm8775", | ||
131 | }; | ||
132 | |||
133 | |||
134 | static const unsigned char *module_i2c_addresses[] = { | ||
135 | [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63", | ||
136 | [PVR2_CLIENT_ID_DEMOD] = "\x43", | ||
137 | [PVR2_CLIENT_ID_MSP3400] = "\x40", | ||
138 | [PVR2_CLIENT_ID_SAA7115] = "\x21", | ||
139 | [PVR2_CLIENT_ID_WM8775] = "\x1b", | ||
140 | [PVR2_CLIENT_ID_CX25840] = "\x44", | ||
141 | [PVR2_CLIENT_ID_CS53L32A] = "\x11", | ||
142 | }; | ||
143 | |||
144 | |||
107 | /* Define the list of additional controls we'll dynamically construct based | 145 | /* Define the list of additional controls we'll dynamically construct based |
108 | on query of the cx2341x module. */ | 146 | on query of the cx2341x module. */ |
109 | struct pvr2_mpeg_ids { | 147 | struct pvr2_mpeg_ids { |
@@ -277,7 +315,6 @@ static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v); | |||
277 | static void pvr2_hdw_state_sched(struct pvr2_hdw *); | 315 | static void pvr2_hdw_state_sched(struct pvr2_hdw *); |
278 | static int pvr2_hdw_state_eval(struct pvr2_hdw *); | 316 | static int pvr2_hdw_state_eval(struct pvr2_hdw *); |
279 | static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); | 317 | static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long); |
280 | static void pvr2_hdw_worker_i2c(struct work_struct *work); | ||
281 | static void pvr2_hdw_worker_poll(struct work_struct *work); | 318 | static void pvr2_hdw_worker_poll(struct work_struct *work); |
282 | static int pvr2_hdw_wait(struct pvr2_hdw *,int state); | 319 | static int pvr2_hdw_wait(struct pvr2_hdw *,int state); |
283 | static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *); | 320 | static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *); |
@@ -642,7 +679,7 @@ static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp) | |||
642 | unsigned long fv; | 679 | unsigned long fv; |
643 | struct pvr2_hdw *hdw = cptr->hdw; | 680 | struct pvr2_hdw *hdw = cptr->hdw; |
644 | if (hdw->tuner_signal_stale) { | 681 | if (hdw->tuner_signal_stale) { |
645 | pvr2_i2c_core_status_poll(hdw); | 682 | pvr2_hdw_status_poll(hdw); |
646 | } | 683 | } |
647 | fv = hdw->tuner_signal_info.rangehigh; | 684 | fv = hdw->tuner_signal_info.rangehigh; |
648 | if (!fv) { | 685 | if (!fv) { |
@@ -664,7 +701,7 @@ static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp) | |||
664 | unsigned long fv; | 701 | unsigned long fv; |
665 | struct pvr2_hdw *hdw = cptr->hdw; | 702 | struct pvr2_hdw *hdw = cptr->hdw; |
666 | if (hdw->tuner_signal_stale) { | 703 | if (hdw->tuner_signal_stale) { |
667 | pvr2_i2c_core_status_poll(hdw); | 704 | pvr2_hdw_status_poll(hdw); |
668 | } | 705 | } |
669 | fv = hdw->tuner_signal_info.rangelow; | 706 | fv = hdw->tuner_signal_info.rangelow; |
670 | if (!fv) { | 707 | if (!fv) { |
@@ -858,7 +895,7 @@ static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) | |||
858 | static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) | 895 | static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) |
859 | { | 896 | { |
860 | struct pvr2_hdw *hdw = cptr->hdw; | 897 | struct pvr2_hdw *hdw = cptr->hdw; |
861 | pvr2_i2c_core_status_poll(hdw); | 898 | pvr2_hdw_status_poll(hdw); |
862 | *vp = hdw->tuner_signal_info.signal; | 899 | *vp = hdw->tuner_signal_info.signal; |
863 | return 0; | 900 | return 0; |
864 | } | 901 | } |
@@ -868,7 +905,7 @@ static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp) | |||
868 | int val = 0; | 905 | int val = 0; |
869 | unsigned int subchan; | 906 | unsigned int subchan; |
870 | struct pvr2_hdw *hdw = cptr->hdw; | 907 | struct pvr2_hdw *hdw = cptr->hdw; |
871 | pvr2_i2c_core_status_poll(hdw); | 908 | pvr2_hdw_status_poll(hdw); |
872 | subchan = hdw->tuner_signal_info.rxsubchans; | 909 | subchan = hdw->tuner_signal_info.rxsubchans; |
873 | if (subchan & V4L2_TUNER_SUB_MONO) { | 910 | if (subchan & V4L2_TUNER_SUB_MONO) { |
874 | val |= (1 << V4L2_TUNER_MODE_MONO); | 911 | val |= (1 << V4L2_TUNER_MODE_MONO); |
@@ -1283,6 +1320,12 @@ const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *hdw) | |||
1283 | } | 1320 | } |
1284 | 1321 | ||
1285 | 1322 | ||
1323 | const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw) | ||
1324 | { | ||
1325 | return hdw->identifier; | ||
1326 | } | ||
1327 | |||
1328 | |||
1286 | unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) | 1329 | unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw) |
1287 | { | 1330 | { |
1288 | return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio; | 1331 | return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio; |
@@ -1634,33 +1677,27 @@ static const char *pvr2_get_state_name(unsigned int st) | |||
1634 | 1677 | ||
1635 | static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) | 1678 | static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl) |
1636 | { | 1679 | { |
1637 | if (!hdw->decoder_ctrl) { | 1680 | /* Even though we really only care about the video decoder chip at |
1638 | if (!hdw->flag_decoder_missed) { | 1681 | this point, we'll broadcast stream on/off to all sub-devices |
1639 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 1682 | anyway, just in case somebody else wants to hear the |
1640 | "WARNING: No decoder present"); | 1683 | command... */ |
1641 | hdw->flag_decoder_missed = !0; | 1684 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s", |
1642 | trace_stbit("flag_decoder_missed", | 1685 | (enablefl ? "on" : "off")); |
1643 | hdw->flag_decoder_missed); | 1686 | v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl); |
1644 | } | 1687 | if (hdw->decoder_client_id) { |
1645 | return -EIO; | 1688 | /* We get here if the encoder has been noticed. Otherwise |
1689 | we'll issue a warning to the user (which should | ||
1690 | normally never happen). */ | ||
1691 | return 0; | ||
1646 | } | 1692 | } |
1647 | hdw->decoder_ctrl->enable(hdw->decoder_ctrl->ctxt,enablefl); | 1693 | if (!hdw->flag_decoder_missed) { |
1648 | return 0; | 1694 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
1649 | } | 1695 | "WARNING: No decoder present"); |
1650 | 1696 | hdw->flag_decoder_missed = !0; | |
1651 | |||
1652 | void pvr2_hdw_set_decoder(struct pvr2_hdw *hdw,struct pvr2_decoder_ctrl *ptr) | ||
1653 | { | ||
1654 | if (hdw->decoder_ctrl == ptr) return; | ||
1655 | hdw->decoder_ctrl = ptr; | ||
1656 | if (hdw->decoder_ctrl && hdw->flag_decoder_missed) { | ||
1657 | hdw->flag_decoder_missed = 0; | ||
1658 | trace_stbit("flag_decoder_missed", | 1697 | trace_stbit("flag_decoder_missed", |
1659 | hdw->flag_decoder_missed); | 1698 | hdw->flag_decoder_missed); |
1660 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
1661 | "Decoder has appeared"); | ||
1662 | pvr2_hdw_state_sched(hdw); | ||
1663 | } | 1699 | } |
1700 | return -EIO; | ||
1664 | } | 1701 | } |
1665 | 1702 | ||
1666 | 1703 | ||
@@ -1927,6 +1964,166 @@ static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) | |||
1927 | } | 1964 | } |
1928 | 1965 | ||
1929 | 1966 | ||
1967 | static unsigned int pvr2_copy_i2c_addr_list( | ||
1968 | unsigned short *dst, const unsigned char *src, | ||
1969 | unsigned int dst_max) | ||
1970 | { | ||
1971 | unsigned int cnt = 0; | ||
1972 | if (!src) return 0; | ||
1973 | while (src[cnt] && (cnt + 1) < dst_max) { | ||
1974 | dst[cnt] = src[cnt]; | ||
1975 | cnt++; | ||
1976 | } | ||
1977 | dst[cnt] = I2C_CLIENT_END; | ||
1978 | return cnt; | ||
1979 | } | ||
1980 | |||
1981 | |||
1982 | static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | ||
1983 | const struct pvr2_device_client_desc *cd) | ||
1984 | { | ||
1985 | const char *fname; | ||
1986 | unsigned char mid; | ||
1987 | struct v4l2_subdev *sd; | ||
1988 | unsigned int i2ccnt; | ||
1989 | const unsigned char *p; | ||
1990 | /* Arbitrary count - max # i2c addresses we will probe */ | ||
1991 | unsigned short i2caddr[25]; | ||
1992 | |||
1993 | mid = cd->module_id; | ||
1994 | fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL; | ||
1995 | if (!fname) { | ||
1996 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
1997 | "Module ID %u for device %s has no name", | ||
1998 | mid, | ||
1999 | hdw->hdw_desc->description); | ||
2000 | return -EINVAL; | ||
2001 | } | ||
2002 | pvr2_trace(PVR2_TRACE_INIT, | ||
2003 | "Module ID %u (%s) for device %s being loaded...", | ||
2004 | mid, fname, | ||
2005 | hdw->hdw_desc->description); | ||
2006 | |||
2007 | i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list, | ||
2008 | ARRAY_SIZE(i2caddr)); | ||
2009 | if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ? | ||
2010 | module_i2c_addresses[mid] : NULL) != NULL)) { | ||
2011 | /* Second chance: Try default i2c address list */ | ||
2012 | i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p, | ||
2013 | ARRAY_SIZE(i2caddr)); | ||
2014 | if (i2ccnt) { | ||
2015 | pvr2_trace(PVR2_TRACE_INIT, | ||
2016 | "Module ID %u:" | ||
2017 | " Using default i2c address list", | ||
2018 | mid); | ||
2019 | } | ||
2020 | } | ||
2021 | |||
2022 | if (!i2ccnt) { | ||
2023 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2024 | "Module ID %u (%s) for device %s:" | ||
2025 | " No i2c addresses", | ||
2026 | mid, fname, hdw->hdw_desc->description); | ||
2027 | return -EINVAL; | ||
2028 | } | ||
2029 | |||
2030 | /* Note how the 2nd and 3rd arguments are the same for both | ||
2031 | * v4l2_i2c_new_subdev() and v4l2_i2c_new_probed_subdev(). Why? | ||
2032 | * Well the 2nd argument is the module name to load, while the 3rd | ||
2033 | * argument is documented in the framework as being the "chipid" - | ||
2034 | * and every other place where I can find examples of this, the | ||
2035 | * "chipid" appears to just be the module name again. So here we | ||
2036 | * just do the same thing. */ | ||
2037 | if (i2ccnt == 1) { | ||
2038 | pvr2_trace(PVR2_TRACE_INIT, | ||
2039 | "Module ID %u:" | ||
2040 | " Setting up with specified i2c address 0x%x", | ||
2041 | mid, i2caddr[0]); | ||
2042 | sd = v4l2_i2c_new_subdev(&hdw->i2c_adap, | ||
2043 | fname, fname, | ||
2044 | i2caddr[0]); | ||
2045 | } else { | ||
2046 | pvr2_trace(PVR2_TRACE_INIT, | ||
2047 | "Module ID %u:" | ||
2048 | " Setting up with address probe list", | ||
2049 | mid); | ||
2050 | sd = v4l2_i2c_new_probed_subdev(&hdw->i2c_adap, | ||
2051 | fname, fname, | ||
2052 | i2caddr); | ||
2053 | } | ||
2054 | |||
2055 | if (!sd) { | ||
2056 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2057 | "Module ID %u (%s) for device %s failed to load", | ||
2058 | mid, fname, hdw->hdw_desc->description); | ||
2059 | return -EIO; | ||
2060 | } | ||
2061 | |||
2062 | /* Tag this sub-device instance with the module ID we know about. | ||
2063 | In other places we'll use that tag to determine if the instance | ||
2064 | requires special handling. */ | ||
2065 | sd->grp_id = mid; | ||
2066 | |||
2067 | pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname); | ||
2068 | |||
2069 | |||
2070 | /* client-specific setup... */ | ||
2071 | switch (mid) { | ||
2072 | case PVR2_CLIENT_ID_CX25840: | ||
2073 | hdw->decoder_client_id = mid; | ||
2074 | { | ||
2075 | /* | ||
2076 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This | ||
2077 | bit of nuttiness for cx25840 causes that module | ||
2078 | to correctly set up its video scaling. This is | ||
2079 | really a problem in the cx25840 module itself, | ||
2080 | but we work around it here. The problem has not | ||
2081 | been seen in ivtv because there VBI is supported | ||
2082 | and set up. We don't do VBI here (at least not | ||
2083 | yet) and thus we never attempted to even set it | ||
2084 | up. | ||
2085 | */ | ||
2086 | struct v4l2_format fmt; | ||
2087 | pvr2_trace(PVR2_TRACE_INIT, | ||
2088 | "Module ID %u:" | ||
2089 | " Executing cx25840 VBI hack", | ||
2090 | mid); | ||
2091 | memset(&fmt, 0, sizeof(fmt)); | ||
2092 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
2093 | v4l2_device_call_all(&hdw->v4l2_dev, mid, | ||
2094 | video, s_fmt, &fmt); | ||
2095 | } | ||
2096 | break; | ||
2097 | case PVR2_CLIENT_ID_SAA7115: | ||
2098 | hdw->decoder_client_id = mid; | ||
2099 | break; | ||
2100 | default: break; | ||
2101 | } | ||
2102 | |||
2103 | return 0; | ||
2104 | } | ||
2105 | |||
2106 | |||
2107 | static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw) | ||
2108 | { | ||
2109 | unsigned int idx; | ||
2110 | const struct pvr2_string_table *cm; | ||
2111 | const struct pvr2_device_client_table *ct; | ||
2112 | int okFl = !0; | ||
2113 | |||
2114 | cm = &hdw->hdw_desc->client_modules; | ||
2115 | for (idx = 0; idx < cm->cnt; idx++) { | ||
2116 | request_module(cm->lst[idx]); | ||
2117 | } | ||
2118 | |||
2119 | ct = &hdw->hdw_desc->client_table; | ||
2120 | for (idx = 0; idx < ct->cnt; idx++) { | ||
2121 | if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0; | ||
2122 | } | ||
2123 | if (!okFl) pvr2_hdw_render_useless(hdw); | ||
2124 | } | ||
2125 | |||
2126 | |||
1930 | static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | 2127 | static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) |
1931 | { | 2128 | { |
1932 | int ret; | 2129 | int ret; |
@@ -1966,9 +2163,7 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1966 | 2163 | ||
1967 | if (!pvr2_hdw_dev_ok(hdw)) return; | 2164 | if (!pvr2_hdw_dev_ok(hdw)) return; |
1968 | 2165 | ||
1969 | for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { | 2166 | hdw->force_dirty = !0; |
1970 | request_module(hdw->hdw_desc->client_modules.lst[idx]); | ||
1971 | } | ||
1972 | 2167 | ||
1973 | if (!hdw->hdw_desc->flag_no_powerup) { | 2168 | if (!hdw->hdw_desc->flag_no_powerup) { |
1974 | pvr2_hdw_cmd_powerup(hdw); | 2169 | pvr2_hdw_cmd_powerup(hdw); |
@@ -1987,6 +2182,11 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
1987 | pvr2_i2c_core_init(hdw); | 2182 | pvr2_i2c_core_init(hdw); |
1988 | if (!pvr2_hdw_dev_ok(hdw)) return; | 2183 | if (!pvr2_hdw_dev_ok(hdw)) return; |
1989 | 2184 | ||
2185 | pvr2_hdw_load_modules(hdw); | ||
2186 | if (!pvr2_hdw_dev_ok(hdw)) return; | ||
2187 | |||
2188 | v4l2_device_call_all(&hdw->v4l2_dev, 0, core, init, 0); | ||
2189 | |||
1990 | for (idx = 0; idx < CTRLDEF_COUNT; idx++) { | 2190 | for (idx = 0; idx < CTRLDEF_COUNT; idx++) { |
1991 | cptr = hdw->controls + idx; | 2191 | cptr = hdw->controls + idx; |
1992 | if (cptr->info->skip_init) continue; | 2192 | if (cptr->info->skip_init) continue; |
@@ -2024,6 +2224,19 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
2024 | hdw->std_mask_eeprom = V4L2_STD_ALL; | 2224 | hdw->std_mask_eeprom = V4L2_STD_ALL; |
2025 | } | 2225 | } |
2026 | 2226 | ||
2227 | if (hdw->serial_number) { | ||
2228 | idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, | ||
2229 | "sn-%lu", hdw->serial_number); | ||
2230 | } else if (hdw->unit_number >= 0) { | ||
2231 | idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, | ||
2232 | "unit-%c", | ||
2233 | hdw->unit_number + 'a'); | ||
2234 | } else { | ||
2235 | idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1, | ||
2236 | "unit-??"); | ||
2237 | } | ||
2238 | hdw->identifier[idx] = 0; | ||
2239 | |||
2027 | pvr2_hdw_setup_std(hdw); | 2240 | pvr2_hdw_setup_std(hdw); |
2028 | 2241 | ||
2029 | if (!get_default_tuner_type(hdw)) { | 2242 | if (!get_default_tuner_type(hdw)) { |
@@ -2032,8 +2245,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
2032 | hdw->tuner_type); | 2245 | hdw->tuner_type); |
2033 | } | 2246 | } |
2034 | 2247 | ||
2035 | pvr2_i2c_core_check_stale(hdw); | ||
2036 | hdw->tuner_updated = 0; | ||
2037 | 2248 | ||
2038 | if (!pvr2_hdw_dev_ok(hdw)) return; | 2249 | if (!pvr2_hdw_dev_ok(hdw)) return; |
2039 | 2250 | ||
@@ -2171,11 +2382,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2171 | struct pvr2_hdw *hdw = NULL; | 2382 | struct pvr2_hdw *hdw = NULL; |
2172 | int valid_std_mask; | 2383 | int valid_std_mask; |
2173 | struct pvr2_ctrl *cptr; | 2384 | struct pvr2_ctrl *cptr; |
2385 | struct usb_device *usb_dev; | ||
2174 | const struct pvr2_device_desc *hdw_desc; | 2386 | const struct pvr2_device_desc *hdw_desc; |
2175 | __u8 ifnum; | 2387 | __u8 ifnum; |
2176 | struct v4l2_queryctrl qctrl; | 2388 | struct v4l2_queryctrl qctrl; |
2177 | struct pvr2_ctl_info *ciptr; | 2389 | struct pvr2_ctl_info *ciptr; |
2178 | 2390 | ||
2391 | usb_dev = interface_to_usbdev(intf); | ||
2392 | |||
2179 | hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); | 2393 | hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info); |
2180 | 2394 | ||
2181 | if (hdw_desc == NULL) { | 2395 | if (hdw_desc == NULL) { |
@@ -2360,6 +2574,11 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2360 | hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); | 2574 | hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); |
2361 | if (!hdw->ctl_read_urb) goto fail; | 2575 | if (!hdw->ctl_read_urb) goto fail; |
2362 | 2576 | ||
2577 | if (v4l2_device_register(&usb_dev->dev, &hdw->v4l2_dev) != 0) { | ||
2578 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2579 | "Error registering with v4l core, giving up"); | ||
2580 | goto fail; | ||
2581 | } | ||
2363 | mutex_lock(&pvr2_unit_mtx); do { | 2582 | mutex_lock(&pvr2_unit_mtx); do { |
2364 | for (idx = 0; idx < PVR_NUM; idx++) { | 2583 | for (idx = 0; idx < PVR_NUM; idx++) { |
2365 | if (unit_pointers[idx]) continue; | 2584 | if (unit_pointers[idx]) continue; |
@@ -2382,7 +2601,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2382 | 2601 | ||
2383 | hdw->workqueue = create_singlethread_workqueue(hdw->name); | 2602 | hdw->workqueue = create_singlethread_workqueue(hdw->name); |
2384 | INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll); | 2603 | INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll); |
2385 | INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c); | ||
2386 | 2604 | ||
2387 | pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", | 2605 | pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", |
2388 | hdw->unit_number,hdw->name); | 2606 | hdw->unit_number,hdw->name); |
@@ -2391,12 +2609,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2391 | hdw->flag_ok = !0; | 2609 | hdw->flag_ok = !0; |
2392 | 2610 | ||
2393 | hdw->usb_intf = intf; | 2611 | hdw->usb_intf = intf; |
2394 | hdw->usb_dev = interface_to_usbdev(intf); | 2612 | hdw->usb_dev = usb_dev; |
2395 | 2613 | ||
2396 | scnprintf(hdw->bus_info,sizeof(hdw->bus_info), | 2614 | usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info)); |
2397 | "usb %s address %d", | ||
2398 | dev_name(&hdw->usb_dev->dev), | ||
2399 | hdw->usb_dev->devnum); | ||
2400 | 2615 | ||
2401 | ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; | 2616 | ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; |
2402 | usb_set_interface(hdw->usb_dev,ifnum,0); | 2617 | usb_set_interface(hdw->usb_dev,ifnum,0); |
@@ -2454,6 +2669,10 @@ static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) | |||
2454 | hdw->ctl_write_buffer = NULL; | 2669 | hdw->ctl_write_buffer = NULL; |
2455 | } | 2670 | } |
2456 | hdw->flag_disconnected = !0; | 2671 | hdw->flag_disconnected = !0; |
2672 | /* If we don't do this, then there will be a dangling struct device | ||
2673 | reference to our disappearing device persisting inside the V4L | ||
2674 | core... */ | ||
2675 | v4l2_device_disconnect(&hdw->v4l2_dev); | ||
2457 | hdw->usb_dev = NULL; | 2676 | hdw->usb_dev = NULL; |
2458 | hdw->usb_intf = NULL; | 2677 | hdw->usb_intf = NULL; |
2459 | pvr2_hdw_render_useless(hdw); | 2678 | pvr2_hdw_render_useless(hdw); |
@@ -2481,10 +2700,8 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) | |||
2481 | pvr2_stream_destroy(hdw->vid_stream); | 2700 | pvr2_stream_destroy(hdw->vid_stream); |
2482 | hdw->vid_stream = NULL; | 2701 | hdw->vid_stream = NULL; |
2483 | } | 2702 | } |
2484 | if (hdw->decoder_ctrl) { | ||
2485 | hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); | ||
2486 | } | ||
2487 | pvr2_i2c_core_done(hdw); | 2703 | pvr2_i2c_core_done(hdw); |
2704 | v4l2_device_unregister(&hdw->v4l2_dev); | ||
2488 | pvr2_hdw_remove_usb_stuff(hdw); | 2705 | pvr2_hdw_remove_usb_stuff(hdw); |
2489 | mutex_lock(&pvr2_unit_mtx); do { | 2706 | mutex_lock(&pvr2_unit_mtx); do { |
2490 | if ((hdw->unit_number >= 0) && | 2707 | if ((hdw->unit_number >= 0) && |
@@ -2678,6 +2895,150 @@ static const char *get_ctrl_typename(enum pvr2_ctl_type tp) | |||
2678 | } | 2895 | } |
2679 | 2896 | ||
2680 | 2897 | ||
2898 | static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, | ||
2899 | const char *name, int val) | ||
2900 | { | ||
2901 | struct v4l2_control ctrl; | ||
2902 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val); | ||
2903 | memset(&ctrl, 0, sizeof(ctrl)); | ||
2904 | ctrl.id = id; | ||
2905 | ctrl.value = val; | ||
2906 | v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl); | ||
2907 | } | ||
2908 | |||
2909 | #define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ | ||
2910 | if ((hdw)->lab##_dirty || (hdw)->force_dirty) { \ | ||
2911 | pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \ | ||
2912 | } | ||
2913 | |||
2914 | /* Execute whatever commands are required to update the state of all the | ||
2915 | sub-devices so that they match our current control values. */ | ||
2916 | static void pvr2_subdev_update(struct pvr2_hdw *hdw) | ||
2917 | { | ||
2918 | struct v4l2_subdev *sd; | ||
2919 | unsigned int id; | ||
2920 | pvr2_subdev_update_func fp; | ||
2921 | |||
2922 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev update..."); | ||
2923 | |||
2924 | if (hdw->tuner_updated || hdw->force_dirty) { | ||
2925 | struct tuner_setup setup; | ||
2926 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)", | ||
2927 | hdw->tuner_type); | ||
2928 | if (((int)(hdw->tuner_type)) >= 0) { | ||
2929 | setup.addr = ADDR_UNSET; | ||
2930 | setup.type = hdw->tuner_type; | ||
2931 | setup.mode_mask = T_RADIO | T_ANALOG_TV; | ||
2932 | v4l2_device_call_all(&hdw->v4l2_dev, 0, | ||
2933 | tuner, s_type_addr, &setup); | ||
2934 | } | ||
2935 | } | ||
2936 | |||
2937 | if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) { | ||
2938 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard"); | ||
2939 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
2940 | v4l2_device_call_all(&hdw->v4l2_dev, 0, | ||
2941 | tuner, s_radio); | ||
2942 | } else { | ||
2943 | v4l2_std_id vs; | ||
2944 | vs = hdw->std_mask_cur; | ||
2945 | v4l2_device_call_all(&hdw->v4l2_dev, 0, | ||
2946 | tuner, s_std, vs); | ||
2947 | } | ||
2948 | hdw->tuner_signal_stale = !0; | ||
2949 | hdw->cropcap_stale = !0; | ||
2950 | } | ||
2951 | |||
2952 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness); | ||
2953 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast); | ||
2954 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation); | ||
2955 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue); | ||
2956 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute); | ||
2957 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume); | ||
2958 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance); | ||
2959 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass); | ||
2960 | PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble); | ||
2961 | |||
2962 | if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) { | ||
2963 | struct v4l2_tuner vt; | ||
2964 | memset(&vt, 0, sizeof(vt)); | ||
2965 | vt.audmode = hdw->audiomode_val; | ||
2966 | v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt); | ||
2967 | } | ||
2968 | |||
2969 | if (hdw->freqDirty || hdw->force_dirty) { | ||
2970 | unsigned long fv; | ||
2971 | struct v4l2_frequency freq; | ||
2972 | fv = pvr2_hdw_get_cur_freq(hdw); | ||
2973 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv); | ||
2974 | if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw); | ||
2975 | memset(&freq, 0, sizeof(freq)); | ||
2976 | if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { | ||
2977 | /* ((fv * 1000) / 62500) */ | ||
2978 | freq.frequency = (fv * 2) / 125; | ||
2979 | } else { | ||
2980 | freq.frequency = fv / 62500; | ||
2981 | } | ||
2982 | /* tuner-core currently doesn't seem to care about this, but | ||
2983 | let's set it anyway for completeness. */ | ||
2984 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
2985 | freq.type = V4L2_TUNER_RADIO; | ||
2986 | } else { | ||
2987 | freq.type = V4L2_TUNER_ANALOG_TV; | ||
2988 | } | ||
2989 | freq.tuner = 0; | ||
2990 | v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, | ||
2991 | s_frequency, &freq); | ||
2992 | } | ||
2993 | |||
2994 | if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) { | ||
2995 | struct v4l2_format fmt; | ||
2996 | memset(&fmt, 0, sizeof(fmt)); | ||
2997 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
2998 | fmt.fmt.pix.width = hdw->res_hor_val; | ||
2999 | fmt.fmt.pix.height = hdw->res_ver_val; | ||
3000 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)", | ||
3001 | fmt.fmt.pix.width, fmt.fmt.pix.height); | ||
3002 | v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_fmt, &fmt); | ||
3003 | } | ||
3004 | |||
3005 | if (hdw->srate_dirty || hdw->force_dirty) { | ||
3006 | u32 val; | ||
3007 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d", | ||
3008 | hdw->srate_val); | ||
3009 | switch (hdw->srate_val) { | ||
3010 | default: | ||
3011 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: | ||
3012 | val = 48000; | ||
3013 | break; | ||
3014 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: | ||
3015 | val = 44100; | ||
3016 | break; | ||
3017 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: | ||
3018 | val = 32000; | ||
3019 | break; | ||
3020 | } | ||
3021 | v4l2_device_call_all(&hdw->v4l2_dev, 0, | ||
3022 | audio, s_clock_freq, val); | ||
3023 | } | ||
3024 | |||
3025 | /* Unable to set crop parameters; there is apparently no equivalent | ||
3026 | for VIDIOC_S_CROP */ | ||
3027 | |||
3028 | v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { | ||
3029 | id = sd->grp_id; | ||
3030 | if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue; | ||
3031 | fp = pvr2_module_update_functions[id]; | ||
3032 | if (!fp) continue; | ||
3033 | (*fp)(hdw, sd); | ||
3034 | } | ||
3035 | |||
3036 | if (hdw->tuner_signal_stale || hdw->cropcap_stale) { | ||
3037 | pvr2_hdw_status_poll(hdw); | ||
3038 | } | ||
3039 | } | ||
3040 | |||
3041 | |||
2681 | /* Figure out if we need to commit control changes. If so, mark internal | 3042 | /* Figure out if we need to commit control changes. If so, mark internal |
2682 | state flags to indicate this fact and return true. Otherwise do nothing | 3043 | state flags to indicate this fact and return true. Otherwise do nothing |
2683 | else and return false. */ | 3044 | else and return false. */ |
@@ -2686,7 +3047,7 @@ static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw) | |||
2686 | unsigned int idx; | 3047 | unsigned int idx; |
2687 | struct pvr2_ctrl *cptr; | 3048 | struct pvr2_ctrl *cptr; |
2688 | int value; | 3049 | int value; |
2689 | int commit_flag = 0; | 3050 | int commit_flag = hdw->force_dirty; |
2690 | char buf[100]; | 3051 | char buf[100]; |
2691 | unsigned int bcnt,ccnt; | 3052 | unsigned int bcnt,ccnt; |
2692 | 3053 | ||
@@ -2842,18 +3203,6 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
2842 | cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS); | 3203 | cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS); |
2843 | } | 3204 | } |
2844 | 3205 | ||
2845 | /* Scan i2c core at this point - before we clear all the dirty | ||
2846 | bits. Various parts of the i2c core will notice dirty bits as | ||
2847 | appropriate and arrange to broadcast or directly send updates to | ||
2848 | the client drivers in order to keep everything in sync */ | ||
2849 | pvr2_i2c_core_check_stale(hdw); | ||
2850 | |||
2851 | for (idx = 0; idx < hdw->control_cnt; idx++) { | ||
2852 | cptr = hdw->controls + idx; | ||
2853 | if (!cptr->info->clear_dirty) continue; | ||
2854 | cptr->info->clear_dirty(cptr); | ||
2855 | } | ||
2856 | |||
2857 | if (hdw->active_stream_type != hdw->desired_stream_type) { | 3206 | if (hdw->active_stream_type != hdw->desired_stream_type) { |
2858 | /* Handle any side effects of stream config here */ | 3207 | /* Handle any side effects of stream config here */ |
2859 | hdw->active_stream_type = hdw->desired_stream_type; | 3208 | hdw->active_stream_type = hdw->desired_stream_type; |
@@ -2873,8 +3222,16 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw) | |||
2873 | } | 3222 | } |
2874 | } | 3223 | } |
2875 | 3224 | ||
2876 | /* Now execute i2c core update */ | 3225 | /* Check and update state for all sub-devices. */ |
2877 | pvr2_i2c_core_sync(hdw); | 3226 | pvr2_subdev_update(hdw); |
3227 | |||
3228 | hdw->tuner_updated = 0; | ||
3229 | hdw->force_dirty = 0; | ||
3230 | for (idx = 0; idx < hdw->control_cnt; idx++) { | ||
3231 | cptr = hdw->controls + idx; | ||
3232 | if (!cptr->info->clear_dirty) continue; | ||
3233 | cptr->info->clear_dirty(cptr); | ||
3234 | } | ||
2878 | 3235 | ||
2879 | if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) && | 3236 | if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) && |
2880 | hdw->state_encoder_run) { | 3237 | hdw->state_encoder_run) { |
@@ -2904,15 +3261,6 @@ int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw) | |||
2904 | } | 3261 | } |
2905 | 3262 | ||
2906 | 3263 | ||
2907 | static void pvr2_hdw_worker_i2c(struct work_struct *work) | ||
2908 | { | ||
2909 | struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,worki2csync); | ||
2910 | LOCK_TAKE(hdw->big_lock); do { | ||
2911 | pvr2_i2c_core_sync(hdw); | ||
2912 | } while (0); LOCK_GIVE(hdw->big_lock); | ||
2913 | } | ||
2914 | |||
2915 | |||
2916 | static void pvr2_hdw_worker_poll(struct work_struct *work) | 3264 | static void pvr2_hdw_worker_poll(struct work_struct *work) |
2917 | { | 3265 | { |
2918 | int fl = 0; | 3266 | int fl = 0; |
@@ -2973,7 +3321,7 @@ int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) | |||
2973 | void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) | 3321 | void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw) |
2974 | { | 3322 | { |
2975 | LOCK_TAKE(hdw->big_lock); do { | 3323 | LOCK_TAKE(hdw->big_lock); do { |
2976 | pvr2_i2c_core_status_poll(hdw); | 3324 | pvr2_hdw_status_poll(hdw); |
2977 | } while (0); LOCK_GIVE(hdw->big_lock); | 3325 | } while (0); LOCK_GIVE(hdw->big_lock); |
2978 | } | 3326 | } |
2979 | 3327 | ||
@@ -2983,7 +3331,7 @@ static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw) | |||
2983 | if (!hdw->cropcap_stale) { | 3331 | if (!hdw->cropcap_stale) { |
2984 | return 0; | 3332 | return 0; |
2985 | } | 3333 | } |
2986 | pvr2_i2c_core_status_poll(hdw); | 3334 | pvr2_hdw_status_poll(hdw); |
2987 | if (hdw->cropcap_stale) { | 3335 | if (hdw->cropcap_stale) { |
2988 | return -EIO; | 3336 | return -EIO; |
2989 | } | 3337 | } |
@@ -3010,7 +3358,7 @@ int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp) | |||
3010 | { | 3358 | { |
3011 | LOCK_TAKE(hdw->big_lock); do { | 3359 | LOCK_TAKE(hdw->big_lock); do { |
3012 | if (hdw->tuner_signal_stale) { | 3360 | if (hdw->tuner_signal_stale) { |
3013 | pvr2_i2c_core_status_poll(hdw); | 3361 | pvr2_hdw_status_poll(hdw); |
3014 | } | 3362 | } |
3015 | memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); | 3363 | memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner)); |
3016 | } while (0); LOCK_GIVE(hdw->big_lock); | 3364 | } while (0); LOCK_GIVE(hdw->big_lock); |
@@ -3029,11 +3377,8 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) | |||
3029 | { | 3377 | { |
3030 | int nr = pvr2_hdw_get_unit_number(hdw); | 3378 | int nr = pvr2_hdw_get_unit_number(hdw); |
3031 | LOCK_TAKE(hdw->big_lock); do { | 3379 | LOCK_TAKE(hdw->big_lock); do { |
3032 | hdw->log_requested = !0; | ||
3033 | printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); | 3380 | printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); |
3034 | pvr2_i2c_core_check_stale(hdw); | 3381 | v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status); |
3035 | hdw->log_requested = 0; | ||
3036 | pvr2_i2c_core_sync(hdw); | ||
3037 | pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); | 3382 | pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); |
3038 | cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); | 3383 | cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); |
3039 | pvr2_hdw_state_log_state(hdw); | 3384 | pvr2_hdw_state_log_state(hdw); |
@@ -3716,22 +4061,16 @@ int pvr2_hdw_cmd_powerdown(struct pvr2_hdw *hdw) | |||
3716 | 4061 | ||
3717 | int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) | 4062 | int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) |
3718 | { | 4063 | { |
3719 | if (!hdw->decoder_ctrl) { | ||
3720 | pvr2_trace(PVR2_TRACE_INIT, | ||
3721 | "Unable to reset decoder: nothing attached"); | ||
3722 | return -ENOTTY; | ||
3723 | } | ||
3724 | |||
3725 | if (!hdw->decoder_ctrl->force_reset) { | ||
3726 | pvr2_trace(PVR2_TRACE_INIT, | ||
3727 | "Unable to reset decoder: not implemented"); | ||
3728 | return -ENOTTY; | ||
3729 | } | ||
3730 | |||
3731 | pvr2_trace(PVR2_TRACE_INIT, | 4064 | pvr2_trace(PVR2_TRACE_INIT, |
3732 | "Requesting decoder reset"); | 4065 | "Requesting decoder reset"); |
3733 | hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); | 4066 | if (hdw->decoder_client_id) { |
3734 | return 0; | 4067 | v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, |
4068 | core, reset, 0); | ||
4069 | return 0; | ||
4070 | } | ||
4071 | pvr2_trace(PVR2_TRACE_INIT, | ||
4072 | "Unable to reset decoder: nothing attached"); | ||
4073 | return -ENOTTY; | ||
3735 | } | 4074 | } |
3736 | 4075 | ||
3737 | 4076 | ||
@@ -4476,6 +4815,79 @@ static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which, | |||
4476 | } | 4815 | } |
4477 | 4816 | ||
4478 | 4817 | ||
4818 | /* Generate report containing info about attached sub-devices and attached | ||
4819 | i2c clients, including an indication of which attached i2c clients are | ||
4820 | actually sub-devices. */ | ||
4821 | static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw, | ||
4822 | char *buf, unsigned int acnt) | ||
4823 | { | ||
4824 | struct v4l2_subdev *sd; | ||
4825 | unsigned int tcnt = 0; | ||
4826 | unsigned int ccnt; | ||
4827 | struct i2c_client *client; | ||
4828 | struct list_head *item; | ||
4829 | void *cd; | ||
4830 | const char *p; | ||
4831 | unsigned int id; | ||
4832 | |||
4833 | ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers:"); | ||
4834 | tcnt += ccnt; | ||
4835 | v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { | ||
4836 | id = sd->grp_id; | ||
4837 | p = NULL; | ||
4838 | if (id < ARRAY_SIZE(module_names)) p = module_names[id]; | ||
4839 | if (p) { | ||
4840 | ccnt = scnprintf(buf + tcnt, acnt - tcnt, " %s", p); | ||
4841 | tcnt += ccnt; | ||
4842 | } else { | ||
4843 | ccnt = scnprintf(buf + tcnt, acnt - tcnt, | ||
4844 | " (unknown id=%u)", id); | ||
4845 | tcnt += ccnt; | ||
4846 | } | ||
4847 | } | ||
4848 | ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); | ||
4849 | tcnt += ccnt; | ||
4850 | |||
4851 | ccnt = scnprintf(buf + tcnt, acnt - tcnt, "I2C clients:\n"); | ||
4852 | tcnt += ccnt; | ||
4853 | |||
4854 | mutex_lock(&hdw->i2c_adap.clist_lock); | ||
4855 | list_for_each(item, &hdw->i2c_adap.clients) { | ||
4856 | client = list_entry(item, struct i2c_client, list); | ||
4857 | ccnt = scnprintf(buf + tcnt, acnt - tcnt, | ||
4858 | " %s: i2c=%02x", client->name, client->addr); | ||
4859 | tcnt += ccnt; | ||
4860 | cd = i2c_get_clientdata(client); | ||
4861 | v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) { | ||
4862 | if (cd == sd) { | ||
4863 | id = sd->grp_id; | ||
4864 | p = NULL; | ||
4865 | if (id < ARRAY_SIZE(module_names)) { | ||
4866 | p = module_names[id]; | ||
4867 | } | ||
4868 | if (p) { | ||
4869 | ccnt = scnprintf(buf + tcnt, | ||
4870 | acnt - tcnt, | ||
4871 | " subdev=%s", p); | ||
4872 | tcnt += ccnt; | ||
4873 | } else { | ||
4874 | ccnt = scnprintf(buf + tcnt, | ||
4875 | acnt - tcnt, | ||
4876 | " subdev= id %u)", | ||
4877 | id); | ||
4878 | tcnt += ccnt; | ||
4879 | } | ||
4880 | break; | ||
4881 | } | ||
4882 | } | ||
4883 | ccnt = scnprintf(buf + tcnt, acnt - tcnt, "\n"); | ||
4884 | tcnt += ccnt; | ||
4885 | } | ||
4886 | mutex_unlock(&hdw->i2c_adap.clist_lock); | ||
4887 | return tcnt; | ||
4888 | } | ||
4889 | |||
4890 | |||
4479 | unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, | 4891 | unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, |
4480 | char *buf,unsigned int acnt) | 4892 | char *buf,unsigned int acnt) |
4481 | { | 4893 | { |
@@ -4490,6 +4902,8 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, | |||
4490 | buf[0] = '\n'; ccnt = 1; | 4902 | buf[0] = '\n'; ccnt = 1; |
4491 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | 4903 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; |
4492 | } | 4904 | } |
4905 | ccnt = pvr2_hdw_report_clients(hdw, buf, acnt); | ||
4906 | bcnt += ccnt; acnt -= ccnt; buf += ccnt; | ||
4493 | LOCK_GIVE(hdw->big_lock); | 4907 | LOCK_GIVE(hdw->big_lock); |
4494 | return bcnt; | 4908 | return bcnt; |
4495 | } | 4909 | } |
@@ -4497,14 +4911,25 @@ unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw, | |||
4497 | 4911 | ||
4498 | static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) | 4912 | static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw) |
4499 | { | 4913 | { |
4500 | char buf[128]; | 4914 | char buf[256]; |
4501 | unsigned int idx,ccnt; | 4915 | unsigned int idx, ccnt; |
4916 | unsigned int lcnt, ucnt; | ||
4502 | 4917 | ||
4503 | for (idx = 0; ; idx++) { | 4918 | for (idx = 0; ; idx++) { |
4504 | ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf)); | 4919 | ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf)); |
4505 | if (!ccnt) break; | 4920 | if (!ccnt) break; |
4506 | printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf); | 4921 | printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf); |
4507 | } | 4922 | } |
4923 | ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf)); | ||
4924 | ucnt = 0; | ||
4925 | while (ucnt < ccnt) { | ||
4926 | lcnt = 0; | ||
4927 | while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) { | ||
4928 | lcnt++; | ||
4929 | } | ||
4930 | printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt); | ||
4931 | ucnt += lcnt + 1; | ||
4932 | } | ||
4508 | } | 4933 | } |
4509 | 4934 | ||
4510 | 4935 | ||
@@ -4641,6 +5066,30 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) | |||
4641 | } | 5066 | } |
4642 | 5067 | ||
4643 | 5068 | ||
5069 | void pvr2_hdw_status_poll(struct pvr2_hdw *hdw) | ||
5070 | { | ||
5071 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; | ||
5072 | memset(vtp, 0, sizeof(*vtp)); | ||
5073 | hdw->tuner_signal_stale = 0; | ||
5074 | /* Note: There apparently is no replacement for VIDIOC_CROPCAP | ||
5075 | using v4l2-subdev - therefore we can't support that AT ALL right | ||
5076 | now. (Of course, no sub-drivers seem to implement it either. | ||
5077 | But now it's a a chicken and egg problem...) */ | ||
5078 | v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, | ||
5079 | &hdw->tuner_signal_info); | ||
5080 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll" | ||
5081 | " type=%u strength=%u audio=0x%x cap=0x%x" | ||
5082 | " low=%u hi=%u", | ||
5083 | vtp->type, | ||
5084 | vtp->signal, vtp->rxsubchans, vtp->capability, | ||
5085 | vtp->rangelow, vtp->rangehigh); | ||
5086 | |||
5087 | /* We have to do this to avoid getting into constant polling if | ||
5088 | there's nobody to answer a poll of cropcap info. */ | ||
5089 | hdw->cropcap_stale = 0; | ||
5090 | } | ||
5091 | |||
5092 | |||
4644 | unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) | 5093 | unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw) |
4645 | { | 5094 | { |
4646 | return hdw->input_avail_mask; | 5095 | return hdw->input_avail_mask; |
@@ -4736,7 +5185,6 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
4736 | int setFl, u64 *val_ptr) | 5185 | int setFl, u64 *val_ptr) |
4737 | { | 5186 | { |
4738 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 5187 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
4739 | struct pvr2_i2c_client *cp; | ||
4740 | struct v4l2_dbg_register req; | 5188 | struct v4l2_dbg_register req; |
4741 | int stat = 0; | 5189 | int stat = 0; |
4742 | int okFl = 0; | 5190 | int okFl = 0; |
@@ -4746,21 +5194,9 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, | |||
4746 | req.match = *match; | 5194 | req.match = *match; |
4747 | req.reg = reg_id; | 5195 | req.reg = reg_id; |
4748 | if (setFl) req.val = *val_ptr; | 5196 | if (setFl) req.val = *val_ptr; |
4749 | mutex_lock(&hdw->i2c_list_lock); do { | 5197 | /* It would be nice to know if a sub-device answered the request */ |
4750 | list_for_each_entry(cp, &hdw->i2c_clients, list) { | 5198 | v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req); |
4751 | if (!v4l2_chip_match_i2c_client( | 5199 | if (!setFl) *val_ptr = req.val; |
4752 | cp->client, | ||
4753 | &req.match)) { | ||
4754 | continue; | ||
4755 | } | ||
4756 | stat = pvr2_i2c_client_cmd( | ||
4757 | cp,(setFl ? VIDIOC_DBG_S_REGISTER : | ||
4758 | VIDIOC_DBG_G_REGISTER),&req); | ||
4759 | if (!setFl) *val_ptr = req.val; | ||
4760 | okFl = !0; | ||
4761 | break; | ||
4762 | } | ||
4763 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
4764 | if (okFl) { | 5200 | if (okFl) { |
4765 | return stat; | 5201 | return stat; |
4766 | } | 5202 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 1b4fec337c6b..7b6940554e9a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h | |||
@@ -132,6 +132,9 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *); | |||
132 | /* Retrieve bus location info of device */ | 132 | /* Retrieve bus location info of device */ |
133 | const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *); | 133 | const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *); |
134 | 134 | ||
135 | /* Retrieve per-instance string identifier for this specific device */ | ||
136 | const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *); | ||
137 | |||
135 | /* Called when hardware has been unplugged */ | 138 | /* Called when hardware has been unplugged */ |
136 | void pvr2_hdw_disconnect(struct pvr2_hdw *); | 139 | void pvr2_hdw_disconnect(struct pvr2_hdw *); |
137 | 140 | ||
@@ -236,8 +239,7 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, | |||
236 | enum pvr2_v4l_type index,int); | 239 | enum pvr2_v4l_type index,int); |
237 | 240 | ||
238 | /* Direct read/write access to chip's registers: | 241 | /* Direct read/write access to chip's registers: |
239 | match_type - how to interpret match_chip (e.g. driver ID, i2c address) | 242 | match - specify criteria to identify target chip (this is a v4l dbg struct) |
240 | match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) | ||
241 | reg_id - register number to access | 243 | reg_id - register number to access |
242 | setFl - true to set the register, false to read it | 244 | setFl - true to set the register, false to read it |
243 | val_ptr - storage location for source / result. */ | 245 | val_ptr - storage location for source / result. */ |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c deleted file mode 100644 index 94a47718e88e..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include "pvrusb2-i2c-core.h" | ||
23 | #include "pvrusb2-hdw-internal.h" | ||
24 | #include "pvrusb2-debug.h" | ||
25 | #include "pvrusb2-i2c-cmd-v4l2.h" | ||
26 | #include "pvrusb2-audio.h" | ||
27 | #include "pvrusb2-tuner.h" | ||
28 | #include "pvrusb2-video-v4l.h" | ||
29 | #include "pvrusb2-cx2584x-v4l.h" | ||
30 | #include "pvrusb2-wm8775.h" | ||
31 | |||
32 | #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) | ||
33 | |||
34 | #define OP_STANDARD 0 | ||
35 | #define OP_AUDIOMODE 1 | ||
36 | #define OP_BCSH 2 | ||
37 | #define OP_VOLUME 3 | ||
38 | #define OP_FREQ 4 | ||
39 | #define OP_AUDIORATE 5 | ||
40 | #define OP_CROP 6 | ||
41 | #define OP_SIZE 7 | ||
42 | #define OP_LOG 8 | ||
43 | |||
44 | static const struct pvr2_i2c_op * const ops[] = { | ||
45 | [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, | ||
46 | [OP_AUDIOMODE] = &pvr2_i2c_op_v4l2_audiomode, | ||
47 | [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, | ||
48 | [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, | ||
49 | [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, | ||
50 | [OP_CROP] = &pvr2_i2c_op_v4l2_crop, | ||
51 | [OP_SIZE] = &pvr2_i2c_op_v4l2_size, | ||
52 | [OP_LOG] = &pvr2_i2c_op_v4l2_log, | ||
53 | }; | ||
54 | |||
55 | void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | ||
56 | { | ||
57 | int id; | ||
58 | id = cp->client->driver->id; | ||
59 | cp->ctl_mask = ((1 << OP_STANDARD) | | ||
60 | (1 << OP_AUDIOMODE) | | ||
61 | (1 << OP_BCSH) | | ||
62 | (1 << OP_VOLUME) | | ||
63 | (1 << OP_FREQ) | | ||
64 | (1 << OP_CROP) | | ||
65 | (1 << OP_SIZE) | | ||
66 | (1 << OP_LOG)); | ||
67 | cp->status_poll = pvr2_v4l2_cmd_status_poll; | ||
68 | |||
69 | if (id == I2C_DRIVERID_MSP3400) { | ||
70 | if (pvr2_i2c_msp3400_setup(hdw,cp)) { | ||
71 | return; | ||
72 | } | ||
73 | } | ||
74 | if (id == I2C_DRIVERID_TUNER) { | ||
75 | if (pvr2_i2c_tuner_setup(hdw,cp)) { | ||
76 | return; | ||
77 | } | ||
78 | } | ||
79 | if (id == I2C_DRIVERID_CX25840) { | ||
80 | if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) { | ||
81 | return; | ||
82 | } | ||
83 | } | ||
84 | if (id == I2C_DRIVERID_WM8775) { | ||
85 | if (pvr2_i2c_wm8775_setup(hdw,cp)) { | ||
86 | return; | ||
87 | } | ||
88 | } | ||
89 | if (id == I2C_DRIVERID_SAA711X) { | ||
90 | if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) { | ||
91 | return; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | |||
97 | const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx) | ||
98 | { | ||
99 | if (idx >= ARRAY_SIZE(ops)) | ||
100 | return NULL; | ||
101 | return ops[idx]; | ||
102 | } | ||
103 | |||
104 | |||
105 | /* | ||
106 | Stuff for Emacs to see, in order to encourage consistent editing style: | ||
107 | *** Local Variables: *** | ||
108 | *** mode: c *** | ||
109 | *** fill-column: 75 *** | ||
110 | *** tab-width: 8 *** | ||
111 | *** c-basic-offset: 8 *** | ||
112 | *** End: *** | ||
113 | */ | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c deleted file mode 100644 index 16bb11902a52..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c +++ /dev/null | |||
@@ -1,322 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | ||
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "pvrusb2-i2c-cmd-v4l2.h" | ||
23 | #include "pvrusb2-hdw-internal.h" | ||
24 | #include "pvrusb2-debug.h" | ||
25 | #include <linux/videodev2.h> | ||
26 | #include <media/v4l2-common.h> | ||
27 | |||
28 | static void set_standard(struct pvr2_hdw *hdw) | ||
29 | { | ||
30 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_standard"); | ||
31 | |||
32 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
33 | pvr2_i2c_core_cmd(hdw,AUDC_SET_RADIO,NULL); | ||
34 | } else { | ||
35 | v4l2_std_id vs; | ||
36 | vs = hdw->std_mask_cur; | ||
37 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); | ||
38 | } | ||
39 | hdw->tuner_signal_stale = !0; | ||
40 | hdw->cropcap_stale = !0; | ||
41 | } | ||
42 | |||
43 | |||
44 | static int check_standard(struct pvr2_hdw *hdw) | ||
45 | { | ||
46 | return (hdw->input_dirty != 0) || (hdw->std_dirty != 0); | ||
47 | } | ||
48 | |||
49 | |||
50 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = { | ||
51 | .check = check_standard, | ||
52 | .update = set_standard, | ||
53 | .name = "v4l2_standard", | ||
54 | }; | ||
55 | |||
56 | |||
57 | static void set_bcsh(struct pvr2_hdw *hdw) | ||
58 | { | ||
59 | struct v4l2_control ctrl; | ||
60 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh" | ||
61 | " b=%d c=%d s=%d h=%d", | ||
62 | hdw->brightness_val,hdw->contrast_val, | ||
63 | hdw->saturation_val,hdw->hue_val); | ||
64 | memset(&ctrl,0,sizeof(ctrl)); | ||
65 | ctrl.id = V4L2_CID_BRIGHTNESS; | ||
66 | ctrl.value = hdw->brightness_val; | ||
67 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
68 | ctrl.id = V4L2_CID_CONTRAST; | ||
69 | ctrl.value = hdw->contrast_val; | ||
70 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
71 | ctrl.id = V4L2_CID_SATURATION; | ||
72 | ctrl.value = hdw->saturation_val; | ||
73 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
74 | ctrl.id = V4L2_CID_HUE; | ||
75 | ctrl.value = hdw->hue_val; | ||
76 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
77 | } | ||
78 | |||
79 | |||
80 | static int check_bcsh(struct pvr2_hdw *hdw) | ||
81 | { | ||
82 | return (hdw->brightness_dirty || | ||
83 | hdw->contrast_dirty || | ||
84 | hdw->saturation_dirty || | ||
85 | hdw->hue_dirty); | ||
86 | } | ||
87 | |||
88 | |||
89 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = { | ||
90 | .check = check_bcsh, | ||
91 | .update = set_bcsh, | ||
92 | .name = "v4l2_bcsh", | ||
93 | }; | ||
94 | |||
95 | |||
96 | static void set_volume(struct pvr2_hdw *hdw) | ||
97 | { | ||
98 | struct v4l2_control ctrl; | ||
99 | pvr2_trace(PVR2_TRACE_CHIPS, | ||
100 | "i2c v4l2 set_volume" | ||
101 | "(vol=%d bal=%d bas=%d treb=%d mute=%d)", | ||
102 | hdw->volume_val, | ||
103 | hdw->balance_val, | ||
104 | hdw->bass_val, | ||
105 | hdw->treble_val, | ||
106 | hdw->mute_val); | ||
107 | memset(&ctrl,0,sizeof(ctrl)); | ||
108 | ctrl.id = V4L2_CID_AUDIO_MUTE; | ||
109 | ctrl.value = hdw->mute_val ? 1 : 0; | ||
110 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
111 | ctrl.id = V4L2_CID_AUDIO_VOLUME; | ||
112 | ctrl.value = hdw->volume_val; | ||
113 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
114 | ctrl.id = V4L2_CID_AUDIO_BALANCE; | ||
115 | ctrl.value = hdw->balance_val; | ||
116 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
117 | ctrl.id = V4L2_CID_AUDIO_BASS; | ||
118 | ctrl.value = hdw->bass_val; | ||
119 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
120 | ctrl.id = V4L2_CID_AUDIO_TREBLE; | ||
121 | ctrl.value = hdw->treble_val; | ||
122 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); | ||
123 | } | ||
124 | |||
125 | |||
126 | static int check_volume(struct pvr2_hdw *hdw) | ||
127 | { | ||
128 | return (hdw->volume_dirty || | ||
129 | hdw->balance_dirty || | ||
130 | hdw->bass_dirty || | ||
131 | hdw->treble_dirty || | ||
132 | hdw->mute_dirty); | ||
133 | } | ||
134 | |||
135 | |||
136 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = { | ||
137 | .check = check_volume, | ||
138 | .update = set_volume, | ||
139 | .name = "v4l2_volume", | ||
140 | }; | ||
141 | |||
142 | |||
143 | static void set_audiomode(struct pvr2_hdw *hdw) | ||
144 | { | ||
145 | struct v4l2_tuner vt; | ||
146 | memset(&vt,0,sizeof(vt)); | ||
147 | vt.audmode = hdw->audiomode_val; | ||
148 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_TUNER,&vt); | ||
149 | } | ||
150 | |||
151 | |||
152 | static int check_audiomode(struct pvr2_hdw *hdw) | ||
153 | { | ||
154 | return (hdw->input_dirty || | ||
155 | hdw->audiomode_dirty); | ||
156 | } | ||
157 | |||
158 | |||
159 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode = { | ||
160 | .check = check_audiomode, | ||
161 | .update = set_audiomode, | ||
162 | .name = "v4l2_audiomode", | ||
163 | }; | ||
164 | |||
165 | |||
166 | static void set_frequency(struct pvr2_hdw *hdw) | ||
167 | { | ||
168 | unsigned long fv; | ||
169 | struct v4l2_frequency freq; | ||
170 | fv = pvr2_hdw_get_cur_freq(hdw); | ||
171 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); | ||
172 | if (hdw->tuner_signal_stale) { | ||
173 | pvr2_i2c_core_status_poll(hdw); | ||
174 | } | ||
175 | memset(&freq,0,sizeof(freq)); | ||
176 | if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) { | ||
177 | // ((fv * 1000) / 62500) | ||
178 | freq.frequency = (fv * 2) / 125; | ||
179 | } else { | ||
180 | freq.frequency = fv / 62500; | ||
181 | } | ||
182 | /* tuner-core currently doesn't seem to care about this, but | ||
183 | let's set it anyway for completeness. */ | ||
184 | if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) { | ||
185 | freq.type = V4L2_TUNER_RADIO; | ||
186 | } else { | ||
187 | freq.type = V4L2_TUNER_ANALOG_TV; | ||
188 | } | ||
189 | freq.tuner = 0; | ||
190 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); | ||
191 | } | ||
192 | |||
193 | |||
194 | static int check_frequency(struct pvr2_hdw *hdw) | ||
195 | { | ||
196 | return hdw->freqDirty != 0; | ||
197 | } | ||
198 | |||
199 | |||
200 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = { | ||
201 | .check = check_frequency, | ||
202 | .update = set_frequency, | ||
203 | .name = "v4l2_freq", | ||
204 | }; | ||
205 | |||
206 | |||
207 | static void set_size(struct pvr2_hdw *hdw) | ||
208 | { | ||
209 | struct v4l2_format fmt; | ||
210 | |||
211 | memset(&fmt,0,sizeof(fmt)); | ||
212 | |||
213 | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
214 | fmt.fmt.pix.width = hdw->res_hor_val; | ||
215 | fmt.fmt.pix.height = hdw->res_ver_val; | ||
216 | |||
217 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)", | ||
218 | fmt.fmt.pix.width,fmt.fmt.pix.height); | ||
219 | |||
220 | pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt); | ||
221 | } | ||
222 | |||
223 | |||
224 | static int check_size(struct pvr2_hdw *hdw) | ||
225 | { | ||
226 | return (hdw->res_hor_dirty || hdw->res_ver_dirty); | ||
227 | } | ||
228 | |||
229 | |||
230 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { | ||
231 | .check = check_size, | ||
232 | .update = set_size, | ||
233 | .name = "v4l2_size", | ||
234 | }; | ||
235 | |||
236 | |||
237 | static void set_crop(struct pvr2_hdw *hdw) | ||
238 | { | ||
239 | struct v4l2_crop crop; | ||
240 | |||
241 | memset(&crop, 0, sizeof crop); | ||
242 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
243 | crop.c.left = hdw->cropl_val; | ||
244 | crop.c.top = hdw->cropt_val; | ||
245 | crop.c.height = hdw->croph_val; | ||
246 | crop.c.width = hdw->cropw_val; | ||
247 | |||
248 | pvr2_trace(PVR2_TRACE_CHIPS, | ||
249 | "i2c v4l2 set_crop crop=%d:%d:%d:%d", | ||
250 | crop.c.width, crop.c.height, crop.c.left, crop.c.top); | ||
251 | |||
252 | pvr2_i2c_core_cmd(hdw, VIDIOC_S_CROP, &crop); | ||
253 | } | ||
254 | |||
255 | static int check_crop(struct pvr2_hdw *hdw) | ||
256 | { | ||
257 | return (hdw->cropl_dirty || hdw->cropt_dirty || | ||
258 | hdw->cropw_dirty || hdw->croph_dirty); | ||
259 | } | ||
260 | |||
261 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop = { | ||
262 | .check = check_crop, | ||
263 | .update = set_crop, | ||
264 | .name = "v4l2_crop", | ||
265 | }; | ||
266 | |||
267 | |||
268 | static void do_log(struct pvr2_hdw *hdw) | ||
269 | { | ||
270 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); | ||
271 | pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL); | ||
272 | |||
273 | } | ||
274 | |||
275 | |||
276 | static int check_log(struct pvr2_hdw *hdw) | ||
277 | { | ||
278 | return hdw->log_requested != 0; | ||
279 | } | ||
280 | |||
281 | |||
282 | const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = { | ||
283 | .check = check_log, | ||
284 | .update = do_log, | ||
285 | .name = "v4l2_log", | ||
286 | }; | ||
287 | |||
288 | |||
289 | void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) | ||
290 | { | ||
291 | pvr2_i2c_client_cmd(cp, | ||
292 | (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL); | ||
293 | } | ||
294 | |||
295 | |||
296 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *cp) | ||
297 | { | ||
298 | int stat; | ||
299 | struct pvr2_hdw *hdw = cp->hdw; | ||
300 | if (hdw->cropcap_stale) { | ||
301 | hdw->cropcap_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
302 | stat = pvr2_i2c_client_cmd(cp, VIDIOC_CROPCAP, | ||
303 | &hdw->cropcap_info); | ||
304 | if (stat == 0) { | ||
305 | /* Check was successful, so the data is no | ||
306 | longer considered stale. */ | ||
307 | hdw->cropcap_stale = 0; | ||
308 | } | ||
309 | } | ||
310 | pvr2_i2c_client_cmd(cp, VIDIOC_G_TUNER, &hdw->tuner_signal_info); | ||
311 | } | ||
312 | |||
313 | |||
314 | /* | ||
315 | Stuff for Emacs to see, in order to encourage consistent editing style: | ||
316 | *** Local Variables: *** | ||
317 | *** mode: c *** | ||
318 | *** fill-column: 70 *** | ||
319 | *** tab-width: 8 *** | ||
320 | *** c-basic-offset: 8 *** | ||
321 | *** End: *** | ||
322 | */ | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h deleted file mode 100644 index eb744a20610d..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | ||
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __PVRUSB2_CMD_V4L2_H | ||
23 | #define __PVRUSB2_CMD_V4L2_H | ||
24 | |||
25 | #include "pvrusb2-i2c-core.h" | ||
26 | |||
27 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; | ||
28 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_radio; | ||
29 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; | ||
30 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; | ||
31 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; | ||
32 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_crop; | ||
33 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; | ||
34 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_audiomode; | ||
35 | extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; | ||
36 | |||
37 | void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); | ||
38 | void pvr2_v4l2_cmd_status_poll(struct pvr2_i2c_client *); | ||
39 | |||
40 | #endif /* __PVRUSB2_CMD_V4L2_H */ | ||
41 | |||
42 | /* | ||
43 | Stuff for Emacs to see, in order to encourage consistent editing style: | ||
44 | *** Local Variables: *** | ||
45 | *** mode: c *** | ||
46 | *** fill-column: 70 *** | ||
47 | *** tab-width: 8 *** | ||
48 | *** c-basic-offset: 8 *** | ||
49 | *** End: *** | ||
50 | */ | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c index d6a35401fefb..9464862745fa 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * | 18 | * |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/i2c.h> | ||
21 | #include "pvrusb2-i2c-core.h" | 22 | #include "pvrusb2-i2c-core.h" |
22 | #include "pvrusb2-hdw-internal.h" | 23 | #include "pvrusb2-hdw-internal.h" |
23 | #include "pvrusb2-debug.h" | 24 | #include "pvrusb2-debug.h" |
@@ -29,8 +30,7 @@ | |||
29 | /* | 30 | /* |
30 | 31 | ||
31 | This module attempts to implement a compliant I2C adapter for the pvrusb2 | 32 | This module attempts to implement a compliant I2C adapter for the pvrusb2 |
32 | device. By doing this we can then make use of existing functionality in | 33 | device. |
33 | V4L (e.g. tuner.c) rather than rolling our own. | ||
34 | 34 | ||
35 | */ | 35 | */ |
36 | 36 | ||
@@ -42,10 +42,6 @@ static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 }; | |||
42 | module_param_array(ir_mode, int, NULL, 0444); | 42 | module_param_array(ir_mode, int, NULL, 0444); |
43 | MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); | 43 | MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR"); |
44 | 44 | ||
45 | static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, | ||
46 | unsigned int detail, | ||
47 | char *buf,unsigned int maxlen); | ||
48 | |||
49 | static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ | 45 | static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ |
50 | u8 i2c_addr, /* I2C address we're talking to */ | 46 | u8 i2c_addr, /* I2C address we're talking to */ |
51 | u8 *data, /* Data to write */ | 47 | u8 *data, /* Data to write */ |
@@ -524,414 +520,13 @@ static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) | |||
524 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; | 520 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; |
525 | } | 521 | } |
526 | 522 | ||
527 | static int pvr2_i2c_core_singleton(struct i2c_client *cp, | ||
528 | unsigned int cmd,void *arg) | ||
529 | { | ||
530 | int stat; | ||
531 | if (!cp) return -EINVAL; | ||
532 | if (!(cp->driver)) return -EINVAL; | ||
533 | if (!(cp->driver->command)) return -EINVAL; | ||
534 | if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; | ||
535 | stat = cp->driver->command(cp,cmd,arg); | ||
536 | module_put(cp->driver->driver.owner); | ||
537 | return stat; | ||
538 | } | ||
539 | |||
540 | int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) | ||
541 | { | ||
542 | int stat; | ||
543 | if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { | ||
544 | char buf[100]; | ||
545 | unsigned int cnt; | ||
546 | cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, | ||
547 | buf,sizeof(buf)); | ||
548 | pvr2_trace(PVR2_TRACE_I2C_CMD, | ||
549 | "i2c COMMAND (code=%u 0x%x) to %.*s", | ||
550 | cmd,cmd,cnt,buf); | ||
551 | } | ||
552 | stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); | ||
553 | if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { | ||
554 | char buf[100]; | ||
555 | unsigned int cnt; | ||
556 | cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, | ||
557 | buf,sizeof(buf)); | ||
558 | pvr2_trace(PVR2_TRACE_I2C_CMD, | ||
559 | "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); | ||
560 | } | ||
561 | return stat; | ||
562 | } | ||
563 | |||
564 | int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) | ||
565 | { | ||
566 | struct pvr2_i2c_client *cp, *ncp; | ||
567 | int stat = -EINVAL; | ||
568 | |||
569 | if (!hdw) return stat; | ||
570 | |||
571 | mutex_lock(&hdw->i2c_list_lock); | ||
572 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { | ||
573 | if (!cp->recv_enable) continue; | ||
574 | mutex_unlock(&hdw->i2c_list_lock); | ||
575 | stat = pvr2_i2c_client_cmd(cp,cmd,arg); | ||
576 | mutex_lock(&hdw->i2c_list_lock); | ||
577 | } | ||
578 | mutex_unlock(&hdw->i2c_list_lock); | ||
579 | return stat; | ||
580 | } | ||
581 | |||
582 | |||
583 | static int handler_check(struct pvr2_i2c_client *cp) | ||
584 | { | ||
585 | struct pvr2_i2c_handler *hp = cp->handler; | ||
586 | if (!hp) return 0; | ||
587 | if (!hp->func_table->check) return 0; | ||
588 | return hp->func_table->check(hp->func_data) != 0; | ||
589 | } | ||
590 | |||
591 | #define BUFSIZE 500 | ||
592 | |||
593 | |||
594 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *hdw) | ||
595 | { | ||
596 | struct pvr2_i2c_client *cp; | ||
597 | mutex_lock(&hdw->i2c_list_lock); do { | ||
598 | struct v4l2_tuner *vtp = &hdw->tuner_signal_info; | ||
599 | memset(vtp,0,sizeof(*vtp)); | ||
600 | list_for_each_entry(cp, &hdw->i2c_clients, list) { | ||
601 | if (!cp->detected_flag) continue; | ||
602 | if (!cp->status_poll) continue; | ||
603 | cp->status_poll(cp); | ||
604 | } | ||
605 | hdw->tuner_signal_stale = 0; | ||
606 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c status poll" | ||
607 | " type=%u strength=%u audio=0x%x cap=0x%x" | ||
608 | " low=%u hi=%u", | ||
609 | vtp->type, | ||
610 | vtp->signal,vtp->rxsubchans,vtp->capability, | ||
611 | vtp->rangelow,vtp->rangehigh); | ||
612 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
613 | } | ||
614 | |||
615 | |||
616 | /* Issue various I2C operations to bring chip-level drivers into sync with | ||
617 | state stored in this driver. */ | ||
618 | void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) | ||
619 | { | ||
620 | unsigned long msk; | ||
621 | unsigned int idx; | ||
622 | struct pvr2_i2c_client *cp, *ncp; | ||
623 | |||
624 | if (!hdw->i2c_linked) return; | ||
625 | if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { | ||
626 | return; | ||
627 | } | ||
628 | mutex_lock(&hdw->i2c_list_lock); do { | ||
629 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); | ||
630 | if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { | ||
631 | /* One or more I2C clients have attached since we | ||
632 | last synced. So scan the list and identify the | ||
633 | new clients. */ | ||
634 | char *buf; | ||
635 | unsigned int cnt; | ||
636 | unsigned long amask = 0; | ||
637 | buf = kmalloc(BUFSIZE,GFP_KERNEL); | ||
638 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); | ||
639 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; | ||
640 | list_for_each_entry(cp, &hdw->i2c_clients, list) { | ||
641 | if (!cp->detected_flag) { | ||
642 | cp->ctl_mask = 0; | ||
643 | pvr2_i2c_probe(hdw,cp); | ||
644 | cp->detected_flag = !0; | ||
645 | msk = cp->ctl_mask; | ||
646 | cnt = 0; | ||
647 | if (buf) { | ||
648 | cnt = pvr2_i2c_client_describe( | ||
649 | cp, | ||
650 | PVR2_I2C_DETAIL_ALL, | ||
651 | buf,BUFSIZE); | ||
652 | } | ||
653 | trace_i2c("Probed: %.*s",cnt,buf); | ||
654 | if (handler_check(cp)) { | ||
655 | hdw->i2c_pend_types |= | ||
656 | PVR2_I2C_PEND_CLIENT; | ||
657 | } | ||
658 | cp->pend_mask = msk; | ||
659 | hdw->i2c_pend_mask |= msk; | ||
660 | hdw->i2c_pend_types |= | ||
661 | PVR2_I2C_PEND_REFRESH; | ||
662 | } | ||
663 | amask |= cp->ctl_mask; | ||
664 | } | ||
665 | hdw->i2c_active_mask = amask; | ||
666 | if (buf) kfree(buf); | ||
667 | } | ||
668 | if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { | ||
669 | /* Need to do one or more global updates. Arrange | ||
670 | for this to happen. */ | ||
671 | unsigned long m2; | ||
672 | pvr2_trace(PVR2_TRACE_I2C_CORE, | ||
673 | "i2c: PEND_STALE (0x%lx)", | ||
674 | hdw->i2c_stale_mask); | ||
675 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; | ||
676 | list_for_each_entry(cp, &hdw->i2c_clients, list) { | ||
677 | m2 = hdw->i2c_stale_mask; | ||
678 | m2 &= cp->ctl_mask; | ||
679 | m2 &= ~cp->pend_mask; | ||
680 | if (m2) { | ||
681 | pvr2_trace(PVR2_TRACE_I2C_CORE, | ||
682 | "i2c: cp=%p setting 0x%lx", | ||
683 | cp,m2); | ||
684 | cp->pend_mask |= m2; | ||
685 | } | ||
686 | } | ||
687 | hdw->i2c_pend_mask |= hdw->i2c_stale_mask; | ||
688 | hdw->i2c_stale_mask = 0; | ||
689 | hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; | ||
690 | } | ||
691 | if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { | ||
692 | /* One or more client handlers are asking for an | ||
693 | update. Run through the list of known clients | ||
694 | and update each one. */ | ||
695 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); | ||
696 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; | ||
697 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, | ||
698 | list) { | ||
699 | if (!cp->handler) continue; | ||
700 | if (!cp->handler->func_table->update) continue; | ||
701 | pvr2_trace(PVR2_TRACE_I2C_CORE, | ||
702 | "i2c: cp=%p update",cp); | ||
703 | mutex_unlock(&hdw->i2c_list_lock); | ||
704 | cp->handler->func_table->update( | ||
705 | cp->handler->func_data); | ||
706 | mutex_lock(&hdw->i2c_list_lock); | ||
707 | /* If client's update function set some | ||
708 | additional pending bits, account for that | ||
709 | here. */ | ||
710 | if (cp->pend_mask & ~hdw->i2c_pend_mask) { | ||
711 | hdw->i2c_pend_mask |= cp->pend_mask; | ||
712 | hdw->i2c_pend_types |= | ||
713 | PVR2_I2C_PEND_REFRESH; | ||
714 | } | ||
715 | } | ||
716 | } | ||
717 | if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { | ||
718 | const struct pvr2_i2c_op *opf; | ||
719 | unsigned long pm; | ||
720 | /* Some actual updates are pending. Walk through | ||
721 | each update type and perform it. */ | ||
722 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" | ||
723 | " (0x%lx)",hdw->i2c_pend_mask); | ||
724 | hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; | ||
725 | pm = hdw->i2c_pend_mask; | ||
726 | hdw->i2c_pend_mask = 0; | ||
727 | for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { | ||
728 | if (!(pm & msk)) continue; | ||
729 | pm &= ~msk; | ||
730 | list_for_each_entry(cp, &hdw->i2c_clients, | ||
731 | list) { | ||
732 | if (cp->pend_mask & msk) { | ||
733 | cp->pend_mask &= ~msk; | ||
734 | cp->recv_enable = !0; | ||
735 | } else { | ||
736 | cp->recv_enable = 0; | ||
737 | } | ||
738 | } | ||
739 | opf = pvr2_i2c_get_op(idx); | ||
740 | if (!opf) continue; | ||
741 | mutex_unlock(&hdw->i2c_list_lock); | ||
742 | opf->update(hdw); | ||
743 | mutex_lock(&hdw->i2c_list_lock); | ||
744 | } | ||
745 | } | ||
746 | pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); | ||
747 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
748 | } | ||
749 | |||
750 | int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) | ||
751 | { | ||
752 | unsigned long msk,sm,pm; | ||
753 | unsigned int idx; | ||
754 | const struct pvr2_i2c_op *opf; | ||
755 | struct pvr2_i2c_client *cp; | ||
756 | unsigned int pt = 0; | ||
757 | |||
758 | pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); | ||
759 | |||
760 | pm = hdw->i2c_active_mask; | ||
761 | sm = 0; | ||
762 | for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { | ||
763 | if (!(msk & pm)) continue; | ||
764 | pm &= ~msk; | ||
765 | opf = pvr2_i2c_get_op(idx); | ||
766 | if (!opf) continue; | ||
767 | if (opf->check(hdw)) { | ||
768 | sm |= msk; | ||
769 | } | ||
770 | } | ||
771 | if (sm) pt |= PVR2_I2C_PEND_STALE; | ||
772 | |||
773 | list_for_each_entry(cp, &hdw->i2c_clients, list) | ||
774 | if (handler_check(cp)) | ||
775 | pt |= PVR2_I2C_PEND_CLIENT; | ||
776 | |||
777 | if (pt) { | ||
778 | mutex_lock(&hdw->i2c_list_lock); do { | ||
779 | hdw->i2c_pend_types |= pt; | ||
780 | hdw->i2c_stale_mask |= sm; | ||
781 | hdw->i2c_pend_mask |= hdw->i2c_stale_mask; | ||
782 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
783 | } | ||
784 | |||
785 | pvr2_trace(PVR2_TRACE_I2C_CORE, | ||
786 | "i2c: types=0x%x stale=0x%lx pend=0x%lx", | ||
787 | hdw->i2c_pend_types, | ||
788 | hdw->i2c_stale_mask, | ||
789 | hdw->i2c_pend_mask); | ||
790 | pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); | ||
791 | |||
792 | return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; | ||
793 | } | ||
794 | |||
795 | static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, | ||
796 | unsigned int detail, | ||
797 | char *buf,unsigned int maxlen) | ||
798 | { | ||
799 | unsigned int ccnt,bcnt; | ||
800 | int spcfl = 0; | ||
801 | const struct pvr2_i2c_op *opf; | ||
802 | |||
803 | ccnt = 0; | ||
804 | if (detail & PVR2_I2C_DETAIL_DEBUG) { | ||
805 | bcnt = scnprintf(buf,maxlen, | ||
806 | "ctxt=%p ctl_mask=0x%lx", | ||
807 | cp,cp->ctl_mask); | ||
808 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
809 | spcfl = !0; | ||
810 | } | ||
811 | bcnt = scnprintf(buf,maxlen, | ||
812 | "%s%s @ 0x%x", | ||
813 | (spcfl ? " " : ""), | ||
814 | cp->client->name, | ||
815 | cp->client->addr); | ||
816 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
817 | if ((detail & PVR2_I2C_DETAIL_HANDLER) && | ||
818 | cp->handler && cp->handler->func_table->describe) { | ||
819 | bcnt = scnprintf(buf,maxlen," ("); | ||
820 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
821 | bcnt = cp->handler->func_table->describe( | ||
822 | cp->handler->func_data,buf,maxlen); | ||
823 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
824 | bcnt = scnprintf(buf,maxlen,")"); | ||
825 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
826 | } | ||
827 | if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { | ||
828 | unsigned int idx; | ||
829 | unsigned long msk,sm; | ||
830 | |||
831 | bcnt = scnprintf(buf,maxlen," ["); | ||
832 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
833 | sm = 0; | ||
834 | spcfl = 0; | ||
835 | for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { | ||
836 | if (!(cp->ctl_mask & msk)) continue; | ||
837 | opf = pvr2_i2c_get_op(idx); | ||
838 | if (opf) { | ||
839 | bcnt = scnprintf(buf,maxlen,"%s%s", | ||
840 | spcfl ? " " : "", | ||
841 | opf->name); | ||
842 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
843 | spcfl = !0; | ||
844 | } else { | ||
845 | sm |= msk; | ||
846 | } | ||
847 | } | ||
848 | if (sm) { | ||
849 | bcnt = scnprintf(buf,maxlen,"%s%lx", | ||
850 | idx != 0 ? " " : "",sm); | ||
851 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
852 | } | ||
853 | bcnt = scnprintf(buf,maxlen,"]"); | ||
854 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
855 | } | ||
856 | return ccnt; | ||
857 | } | ||
858 | |||
859 | unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, | ||
860 | char *buf,unsigned int maxlen) | ||
861 | { | ||
862 | unsigned int ccnt,bcnt; | ||
863 | struct pvr2_i2c_client *cp; | ||
864 | ccnt = 0; | ||
865 | mutex_lock(&hdw->i2c_list_lock); do { | ||
866 | list_for_each_entry(cp, &hdw->i2c_clients, list) { | ||
867 | bcnt = pvr2_i2c_client_describe( | ||
868 | cp, | ||
869 | (PVR2_I2C_DETAIL_HANDLER| | ||
870 | PVR2_I2C_DETAIL_CTLMASK), | ||
871 | buf,maxlen); | ||
872 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
873 | bcnt = scnprintf(buf,maxlen,"\n"); | ||
874 | ccnt += bcnt; buf += bcnt; maxlen -= bcnt; | ||
875 | } | ||
876 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
877 | return ccnt; | ||
878 | } | ||
879 | |||
880 | static int pvr2_i2c_attach_inform(struct i2c_client *client) | 523 | static int pvr2_i2c_attach_inform(struct i2c_client *client) |
881 | { | 524 | { |
882 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); | ||
883 | struct pvr2_i2c_client *cp; | ||
884 | int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); | ||
885 | cp = kzalloc(sizeof(*cp),GFP_KERNEL); | ||
886 | trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", | ||
887 | client->name, | ||
888 | client->addr,cp); | ||
889 | if (!cp) return -ENOMEM; | ||
890 | cp->hdw = hdw; | ||
891 | INIT_LIST_HEAD(&cp->list); | ||
892 | cp->client = client; | ||
893 | mutex_lock(&hdw->i2c_list_lock); do { | ||
894 | hdw->cropcap_stale = !0; | ||
895 | list_add_tail(&cp->list,&hdw->i2c_clients); | ||
896 | hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; | ||
897 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
898 | if (fl) queue_work(hdw->workqueue,&hdw->worki2csync); | ||
899 | return 0; | 525 | return 0; |
900 | } | 526 | } |
901 | 527 | ||
902 | static int pvr2_i2c_detach_inform(struct i2c_client *client) | 528 | static int pvr2_i2c_detach_inform(struct i2c_client *client) |
903 | { | 529 | { |
904 | struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); | ||
905 | struct pvr2_i2c_client *cp, *ncp; | ||
906 | unsigned long amask = 0; | ||
907 | int foundfl = 0; | ||
908 | mutex_lock(&hdw->i2c_list_lock); do { | ||
909 | hdw->cropcap_stale = !0; | ||
910 | list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) { | ||
911 | if (cp->client == client) { | ||
912 | trace_i2c("pvr2_i2c_detach" | ||
913 | " [client=%s @ 0x%x ctxt=%p]", | ||
914 | client->name, | ||
915 | client->addr,cp); | ||
916 | if (cp->handler && | ||
917 | cp->handler->func_table->detach) { | ||
918 | cp->handler->func_table->detach( | ||
919 | cp->handler->func_data); | ||
920 | } | ||
921 | list_del(&cp->list); | ||
922 | kfree(cp); | ||
923 | foundfl = !0; | ||
924 | continue; | ||
925 | } | ||
926 | amask |= cp->ctl_mask; | ||
927 | } | ||
928 | hdw->i2c_active_mask = amask; | ||
929 | } while (0); mutex_unlock(&hdw->i2c_list_lock); | ||
930 | if (!foundfl) { | ||
931 | trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]", | ||
932 | client->name, | ||
933 | client->addr); | ||
934 | } | ||
935 | return 0; | 530 | return 0; |
936 | } | 531 | } |
937 | 532 | ||
@@ -942,7 +537,7 @@ static struct i2c_algorithm pvr2_i2c_algo_template = { | |||
942 | 537 | ||
943 | static struct i2c_adapter pvr2_i2c_adap_template = { | 538 | static struct i2c_adapter pvr2_i2c_adap_template = { |
944 | .owner = THIS_MODULE, | 539 | .owner = THIS_MODULE, |
945 | .class = I2C_CLASS_TV_ANALOG, | 540 | .class = 0, |
946 | .id = I2C_HW_B_BT848, | 541 | .id = I2C_HW_B_BT848, |
947 | .client_register = pvr2_i2c_attach_inform, | 542 | .client_register = pvr2_i2c_attach_inform, |
948 | .client_unregister = pvr2_i2c_detach_inform, | 543 | .client_unregister = pvr2_i2c_detach_inform, |
@@ -1009,12 +604,8 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw) | |||
1009 | hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; | 604 | hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev; |
1010 | hdw->i2c_adap.algo = &hdw->i2c_algo; | 605 | hdw->i2c_adap.algo = &hdw->i2c_algo; |
1011 | hdw->i2c_adap.algo_data = hdw; | 606 | hdw->i2c_adap.algo_data = hdw; |
1012 | hdw->i2c_pend_mask = 0; | ||
1013 | hdw->i2c_stale_mask = 0; | ||
1014 | hdw->i2c_active_mask = 0; | ||
1015 | INIT_LIST_HEAD(&hdw->i2c_clients); | ||
1016 | mutex_init(&hdw->i2c_list_lock); | ||
1017 | hdw->i2c_linked = !0; | 607 | hdw->i2c_linked = !0; |
608 | i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev); | ||
1018 | i2c_add_adapter(&hdw->i2c_adap); | 609 | i2c_add_adapter(&hdw->i2c_adap); |
1019 | if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { | 610 | if (hdw->i2c_func[0x18] == i2c_24xxx_ir) { |
1020 | /* Probe for a different type of IR receiver on this | 611 | /* Probe for a different type of IR receiver on this |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h index 6ef7a1c0e935..6a75769200bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h | |||
@@ -20,68 +20,13 @@ | |||
20 | #ifndef __PVRUSB2_I2C_CORE_H | 20 | #ifndef __PVRUSB2_I2C_CORE_H |
21 | #define __PVRUSB2_I2C_CORE_H | 21 | #define __PVRUSB2_I2C_CORE_H |
22 | 22 | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/i2c.h> | ||
25 | |||
26 | struct pvr2_hdw; | 23 | struct pvr2_hdw; |
27 | struct pvr2_i2c_client; | ||
28 | struct pvr2_i2c_handler; | ||
29 | struct pvr2_i2c_handler_functions; | ||
30 | struct pvr2_i2c_op; | ||
31 | struct pvr2_i2c_op_functions; | ||
32 | |||
33 | struct pvr2_i2c_client { | ||
34 | struct i2c_client *client; | ||
35 | struct pvr2_i2c_handler *handler; | ||
36 | struct list_head list; | ||
37 | struct pvr2_hdw *hdw; | ||
38 | int detected_flag; | ||
39 | int recv_enable; | ||
40 | unsigned long pend_mask; | ||
41 | unsigned long ctl_mask; | ||
42 | void (*status_poll)(struct pvr2_i2c_client *); | ||
43 | }; | ||
44 | |||
45 | struct pvr2_i2c_handler { | ||
46 | void *func_data; | ||
47 | const struct pvr2_i2c_handler_functions *func_table; | ||
48 | }; | ||
49 | |||
50 | struct pvr2_i2c_handler_functions { | ||
51 | void (*detach)(void *); | ||
52 | int (*check)(void *); | ||
53 | void (*update)(void *); | ||
54 | unsigned int (*describe)(void *,char *,unsigned int); | ||
55 | }; | ||
56 | |||
57 | struct pvr2_i2c_op { | ||
58 | int (*check)(struct pvr2_hdw *); | ||
59 | void (*update)(struct pvr2_hdw *); | ||
60 | const char *name; | ||
61 | }; | ||
62 | 24 | ||
63 | void pvr2_i2c_core_init(struct pvr2_hdw *); | 25 | void pvr2_i2c_core_init(struct pvr2_hdw *); |
64 | void pvr2_i2c_core_done(struct pvr2_hdw *); | 26 | void pvr2_i2c_core_done(struct pvr2_hdw *); |
65 | 27 | ||
66 | int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); | ||
67 | int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); | ||
68 | |||
69 | int pvr2_i2c_core_check_stale(struct pvr2_hdw *); | ||
70 | void pvr2_i2c_core_sync(struct pvr2_hdw *); | ||
71 | void pvr2_i2c_core_status_poll(struct pvr2_hdw *); | ||
72 | unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); | ||
73 | #define PVR2_I2C_DETAIL_DEBUG 0x0001 | ||
74 | #define PVR2_I2C_DETAIL_HANDLER 0x0002 | ||
75 | #define PVR2_I2C_DETAIL_CTLMASK 0x0004 | ||
76 | #define PVR2_I2C_DETAIL_ALL (\ | ||
77 | PVR2_I2C_DETAIL_DEBUG |\ | ||
78 | PVR2_I2C_DETAIL_HANDLER |\ | ||
79 | PVR2_I2C_DETAIL_CTLMASK) | ||
80 | |||
81 | void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); | ||
82 | const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); | ||
83 | 28 | ||
84 | #endif /* __PVRUSB2_I2C_CORE_H */ | 29 | #endif /* __PVRUSB2_I2C_ADAPTER_H */ |
85 | 30 | ||
86 | 31 | ||
87 | /* | 32 | /* |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c index 9b3c874d96d6..8689ddb54420 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-main.c +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c | |||
@@ -137,10 +137,10 @@ static int __init pvr_init(void) | |||
137 | ret = usb_register(&pvr_driver); | 137 | ret = usb_register(&pvr_driver); |
138 | 138 | ||
139 | if (ret == 0) | 139 | if (ret == 0) |
140 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 140 | printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":" |
141 | DRIVER_DESC "\n"); | 141 | DRIVER_DESC "\n"); |
142 | if (pvrusb2_debug) | 142 | if (pvrusb2_debug) |
143 | printk(KERN_INFO KBUILD_MODNAME ": Debug mask is %d (0x%x)\n", | 143 | printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n", |
144 | pvrusb2_debug,pvrusb2_debug); | 144 | pvrusb2_debug,pvrusb2_debug); |
145 | 145 | ||
146 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); | 146 | pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete"); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index e641cd971453..e20ba1e6e0ea 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c | |||
@@ -627,16 +627,8 @@ static void class_dev_create(struct pvr2_sysfs *sfp, | |||
627 | pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); | 627 | pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); |
628 | 628 | ||
629 | class_dev->class = &class_ptr->class; | 629 | class_dev->class = &class_ptr->class; |
630 | if (pvr2_hdw_get_sn(sfp->channel.hdw)) { | 630 | dev_set_name(class_dev, "%s", |
631 | dev_set_name(class_dev, "sn-%lu", | 631 | pvr2_hdw_get_device_identifier(sfp->channel.hdw)); |
632 | pvr2_hdw_get_sn(sfp->channel.hdw)); | ||
633 | } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) { | ||
634 | dev_set_name(class_dev, "unit-%c", | ||
635 | pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a'); | ||
636 | } else { | ||
637 | kfree(class_dev); | ||
638 | return; | ||
639 | } | ||
640 | 632 | ||
641 | class_dev->parent = &usb_dev->dev; | 633 | class_dev->parent = &usb_dev->dev; |
642 | 634 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c deleted file mode 100644 index 07775d1aad4e..000000000000 --- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c +++ /dev/null | |||
@@ -1,120 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Isely <isely@pobox.com> | ||
5 | * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include "pvrusb2.h" | ||
23 | #include "pvrusb2-util.h" | ||
24 | #include "pvrusb2-tuner.h" | ||
25 | #include "pvrusb2-hdw-internal.h" | ||
26 | #include "pvrusb2-debug.h" | ||
27 | #include <linux/videodev2.h> | ||
28 | #include <media/tuner.h> | ||
29 | #include <media/v4l2-common.h> | ||
30 | |||
31 | struct pvr2_tuner_handler { | ||
32 | struct pvr2_hdw *hdw; | ||
33 | struct pvr2_i2c_client *client; | ||
34 | struct pvr2_i2c_handler i2c_handler; | ||
35 | int type_update_fl; | ||
36 | }; | ||
37 | |||
38 | |||
39 | static void set_type(struct pvr2_tuner_handler *ctxt) | ||
40 | { | ||
41 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
42 | struct tuner_setup setup; | ||
43 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type); | ||
44 | if (((int)(hdw->tuner_type)) < 0) return; | ||
45 | |||
46 | setup.addr = ADDR_UNSET; | ||
47 | setup.type = hdw->tuner_type; | ||
48 | setup.mode_mask = T_RADIO | T_ANALOG_TV; | ||
49 | /* We may really want mode_mask to be T_ANALOG_TV for now */ | ||
50 | pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup); | ||
51 | ctxt->type_update_fl = 0; | ||
52 | } | ||
53 | |||
54 | |||
55 | static int tuner_check(struct pvr2_tuner_handler *ctxt) | ||
56 | { | ||
57 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
58 | if (hdw->tuner_updated) ctxt->type_update_fl = !0; | ||
59 | return ctxt->type_update_fl != 0; | ||
60 | } | ||
61 | |||
62 | |||
63 | static void tuner_update(struct pvr2_tuner_handler *ctxt) | ||
64 | { | ||
65 | if (ctxt->type_update_fl) set_type(ctxt); | ||
66 | } | ||
67 | |||
68 | |||
69 | static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt) | ||
70 | { | ||
71 | ctxt->client->handler = NULL; | ||
72 | kfree(ctxt); | ||
73 | } | ||
74 | |||
75 | |||
76 | static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt) | ||
77 | { | ||
78 | return scnprintf(buf,cnt,"handler: pvrusb2-tuner"); | ||
79 | } | ||
80 | |||
81 | |||
82 | static const struct pvr2_i2c_handler_functions tuner_funcs = { | ||
83 | .detach = (void (*)(void *))pvr2_tuner_detach, | ||
84 | .check = (int (*)(void *))tuner_check, | ||
85 | .update = (void (*)(void *))tuner_update, | ||
86 | .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe, | ||
87 | }; | ||
88 | |||
89 | |||
90 | int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | ||
91 | { | ||
92 | struct pvr2_tuner_handler *ctxt; | ||
93 | if (cp->handler) return 0; | ||
94 | |||
95 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); | ||
96 | if (!ctxt) return 0; | ||
97 | |||
98 | ctxt->i2c_handler.func_data = ctxt; | ||
99 | ctxt->i2c_handler.func_table = &tuner_funcs; | ||
100 | ctxt->type_update_fl = !0; | ||
101 | ctxt->client = cp; | ||
102 | ctxt->hdw = hdw; | ||
103 | cp->handler = &ctxt->i2c_handler; | ||
104 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up", | ||
105 | cp->client->addr); | ||
106 | return !0; | ||
107 | } | ||
108 | |||
109 | |||
110 | |||
111 | |||
112 | /* | ||
113 | Stuff for Emacs to see, in order to encourage consistent editing style: | ||
114 | *** Local Variables: *** | ||
115 | *** mode: c *** | ||
116 | *** fill-column: 70 *** | ||
117 | *** tab-width: 8 *** | ||
118 | *** c-basic-offset: 8 *** | ||
119 | *** End: *** | ||
120 | */ | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 878fd52a73b3..9e0f2b07b93b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -91,7 +91,7 @@ static struct v4l2_capability pvr_capability ={ | |||
91 | .card = "Hauppauge WinTV pvr-usb2", | 91 | .card = "Hauppauge WinTV pvr-usb2", |
92 | .bus_info = "usb", | 92 | .bus_info = "usb", |
93 | .version = KERNEL_VERSION(0,8,0), | 93 | .version = KERNEL_VERSION(0,8,0), |
94 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | | 94 | .capabilities = (V4L2_CAP_VIDEO_CAPTURE | |
95 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | | 95 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO | |
96 | V4L2_CAP_READWRITE), | 96 | V4L2_CAP_READWRITE), |
97 | .reserved = {0,0,0,0} | 97 | .reserved = {0,0,0,0} |
@@ -952,10 +952,6 @@ static long pvr2_v4l2_ioctl(struct file *file, | |||
952 | unsigned int cmd, unsigned long arg) | 952 | unsigned int cmd, unsigned long arg) |
953 | { | 953 | { |
954 | 954 | ||
955 | /* Temporary hack : use ivtv api until a v4l2 one is available. */ | ||
956 | #define IVTV_IOC_G_CODEC 0xFFEE7703 | ||
957 | #define IVTV_IOC_S_CODEC 0xFFEE7704 | ||
958 | if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0; | ||
959 | return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl); | 955 | return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl); |
960 | } | 956 | } |
961 | 957 | ||
@@ -1268,8 +1264,9 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1268 | dip->minor_type = pvr2_v4l_type_video; | 1264 | dip->minor_type = pvr2_v4l_type_video; |
1269 | nr_ptr = video_nr; | 1265 | nr_ptr = video_nr; |
1270 | if (!dip->stream) { | 1266 | if (!dip->stream) { |
1271 | err("Failed to set up pvrusb2 v4l video dev" | 1267 | pr_err(KBUILD_MODNAME |
1272 | " due to missing stream instance"); | 1268 | ": Failed to set up pvrusb2 v4l video dev" |
1269 | " due to missing stream instance\n"); | ||
1273 | return; | 1270 | return; |
1274 | } | 1271 | } |
1275 | break; | 1272 | break; |
@@ -1286,8 +1283,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1286 | break; | 1283 | break; |
1287 | default: | 1284 | default: |
1288 | /* Bail out (this should be impossible) */ | 1285 | /* Bail out (this should be impossible) */ |
1289 | err("Failed to set up pvrusb2 v4l dev" | 1286 | pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev" |
1290 | " due to unrecognized config"); | 1287 | " due to unrecognized config\n"); |
1291 | return; | 1288 | return; |
1292 | } | 1289 | } |
1293 | 1290 | ||
@@ -1303,7 +1300,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1303 | dip->v4l_type, mindevnum) < 0) && | 1300 | dip->v4l_type, mindevnum) < 0) && |
1304 | (video_register_device(&dip->devbase, | 1301 | (video_register_device(&dip->devbase, |
1305 | dip->v4l_type, -1) < 0)) { | 1302 | dip->v4l_type, -1) < 0)) { |
1306 | err("Failed to register pvrusb2 v4l device"); | 1303 | pr_err(KBUILD_MODNAME |
1304 | ": Failed to register pvrusb2 v4l device\n"); | ||
1307 | } | 1305 | } |
1308 | 1306 | ||
1309 | printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", | 1307 | printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index 4059648c7056..b3862f5554bd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | |||
@@ -28,7 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "pvrusb2-video-v4l.h" | 30 | #include "pvrusb2-video-v4l.h" |
31 | #include "pvrusb2-i2c-cmd-v4l2.h" | 31 | |
32 | 32 | ||
33 | 33 | ||
34 | #include "pvrusb2-hdw-internal.h" | 34 | #include "pvrusb2-hdw-internal.h" |
@@ -39,15 +39,6 @@ | |||
39 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | 41 | ||
42 | struct pvr2_v4l_decoder { | ||
43 | struct pvr2_i2c_handler handler; | ||
44 | struct pvr2_decoder_ctrl ctrl; | ||
45 | struct pvr2_i2c_client *client; | ||
46 | struct pvr2_hdw *hdw; | ||
47 | unsigned long stale_mask; | ||
48 | }; | ||
49 | |||
50 | |||
51 | struct routing_scheme { | 42 | struct routing_scheme { |
52 | const int *def; | 43 | const int *def; |
53 | unsigned int cnt; | 44 | unsigned int cnt; |
@@ -63,190 +54,51 @@ static const int routing_scheme0[] = { | |||
63 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, | 54 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, |
64 | }; | 55 | }; |
65 | 56 | ||
57 | static const int routing_scheme1[] = { | ||
58 | [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, | ||
59 | [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, | ||
60 | [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3, | ||
61 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ | ||
62 | }; | ||
63 | |||
66 | static const struct routing_scheme routing_schemes[] = { | 64 | static const struct routing_scheme routing_schemes[] = { |
67 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { | 65 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { |
68 | .def = routing_scheme0, | 66 | .def = routing_scheme0, |
69 | .cnt = ARRAY_SIZE(routing_scheme0), | 67 | .cnt = ARRAY_SIZE(routing_scheme0), |
70 | }, | 68 | }, |
69 | [PVR2_ROUTING_SCHEME_ONAIR] = { | ||
70 | .def = routing_scheme1, | ||
71 | .cnt = ARRAY_SIZE(routing_scheme1), | ||
72 | }, | ||
71 | }; | 73 | }; |
72 | 74 | ||
73 | static void set_input(struct pvr2_v4l_decoder *ctxt) | 75 | void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
74 | { | ||
75 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
76 | struct v4l2_routing route; | ||
77 | const struct routing_scheme *sp; | ||
78 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | ||
79 | |||
80 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val); | ||
81 | |||
82 | if ((sid < ARRAY_SIZE(routing_schemes)) && | ||
83 | ((sp = routing_schemes + sid) != NULL) && | ||
84 | (hdw->input_val >= 0) && | ||
85 | (hdw->input_val < sp->cnt)) { | ||
86 | route.input = sp->def[hdw->input_val]; | ||
87 | } else { | ||
88 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
89 | "*** WARNING *** i2c v4l2 set_input:" | ||
90 | " Invalid routing scheme (%u) and/or input (%d)", | ||
91 | sid,hdw->input_val); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | route.output = 0; | ||
96 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); | ||
97 | } | ||
98 | |||
99 | |||
100 | static int check_input(struct pvr2_v4l_decoder *ctxt) | ||
101 | { | ||
102 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
103 | return hdw->input_dirty != 0; | ||
104 | } | ||
105 | |||
106 | |||
107 | static void set_audio(struct pvr2_v4l_decoder *ctxt) | ||
108 | { | ||
109 | u32 val; | ||
110 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
111 | |||
112 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d", | ||
113 | hdw->srate_val); | ||
114 | switch (hdw->srate_val) { | ||
115 | default: | ||
116 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: | ||
117 | val = 48000; | ||
118 | break; | ||
119 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: | ||
120 | val = 44100; | ||
121 | break; | ||
122 | case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: | ||
123 | val = 32000; | ||
124 | break; | ||
125 | } | ||
126 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); | ||
127 | } | ||
128 | |||
129 | |||
130 | static int check_audio(struct pvr2_v4l_decoder *ctxt) | ||
131 | { | ||
132 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
133 | return hdw->srate_dirty != 0; | ||
134 | } | ||
135 | |||
136 | |||
137 | struct pvr2_v4l_decoder_ops { | ||
138 | void (*update)(struct pvr2_v4l_decoder *); | ||
139 | int (*check)(struct pvr2_v4l_decoder *); | ||
140 | }; | ||
141 | |||
142 | |||
143 | static const struct pvr2_v4l_decoder_ops decoder_ops[] = { | ||
144 | { .update = set_input, .check = check_input}, | ||
145 | { .update = set_audio, .check = check_audio}, | ||
146 | }; | ||
147 | |||
148 | |||
149 | static void decoder_detach(struct pvr2_v4l_decoder *ctxt) | ||
150 | { | 76 | { |
151 | ctxt->client->handler = NULL; | 77 | if (hdw->input_dirty || hdw->force_dirty) { |
152 | pvr2_hdw_set_decoder(ctxt->hdw,NULL); | 78 | struct v4l2_routing route; |
153 | kfree(ctxt); | 79 | const struct routing_scheme *sp; |
154 | } | 80 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; |
155 | 81 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", | |
156 | 82 | hdw->input_val); | |
157 | static int decoder_check(struct pvr2_v4l_decoder *ctxt) | 83 | if ((sid < ARRAY_SIZE(routing_schemes)) && |
158 | { | 84 | ((sp = routing_schemes + sid) != NULL) && |
159 | unsigned long msk; | 85 | (hdw->input_val >= 0) && |
160 | unsigned int idx; | 86 | (hdw->input_val < sp->cnt)) { |
161 | 87 | route.input = sp->def[hdw->input_val]; | |
162 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { | 88 | } else { |
163 | msk = 1 << idx; | 89 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
164 | if (ctxt->stale_mask & msk) continue; | 90 | "*** WARNING *** subdev v4l2 set_input:" |
165 | if (decoder_ops[idx].check(ctxt)) { | 91 | " Invalid routing scheme (%u)" |
166 | ctxt->stale_mask |= msk; | 92 | " and/or input (%d)", |
93 | sid, hdw->input_val); | ||
94 | return; | ||
167 | } | 95 | } |
96 | route.output = 0; | ||
97 | sd->ops->video->s_routing(sd, &route); | ||
168 | } | 98 | } |
169 | return ctxt->stale_mask != 0; | ||
170 | } | ||
171 | |||
172 | |||
173 | static void decoder_update(struct pvr2_v4l_decoder *ctxt) | ||
174 | { | ||
175 | unsigned long msk; | ||
176 | unsigned int idx; | ||
177 | |||
178 | for (idx = 0; idx < ARRAY_SIZE(decoder_ops); idx++) { | ||
179 | msk = 1 << idx; | ||
180 | if (!(ctxt->stale_mask & msk)) continue; | ||
181 | ctxt->stale_mask &= ~msk; | ||
182 | decoder_ops[idx].update(ctxt); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | |||
187 | static int decoder_detect(struct pvr2_i2c_client *cp) | ||
188 | { | ||
189 | /* Attempt to query the decoder - let's see if it will answer */ | ||
190 | struct v4l2_tuner vt; | ||
191 | int ret; | ||
192 | |||
193 | memset(&vt,0,sizeof(vt)); | ||
194 | ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt); | ||
195 | return ret == 0; /* Return true if it answered */ | ||
196 | } | ||
197 | |||
198 | |||
199 | static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) | ||
200 | { | ||
201 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl); | ||
202 | pvr2_v4l2_cmd_stream(ctxt->client,fl); | ||
203 | } | ||
204 | |||
205 | |||
206 | static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) | ||
207 | { | ||
208 | return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); | ||
209 | } | ||
210 | |||
211 | |||
212 | static const struct pvr2_i2c_handler_functions hfuncs = { | ||
213 | .detach = (void (*)(void *))decoder_detach, | ||
214 | .check = (int (*)(void *))decoder_check, | ||
215 | .update = (void (*)(void *))decoder_update, | ||
216 | .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, | ||
217 | }; | ||
218 | |||
219 | |||
220 | int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, | ||
221 | struct pvr2_i2c_client *cp) | ||
222 | { | ||
223 | struct pvr2_v4l_decoder *ctxt; | ||
224 | |||
225 | if (hdw->decoder_ctrl) return 0; | ||
226 | if (cp->handler) return 0; | ||
227 | if (!decoder_detect(cp)) return 0; | ||
228 | |||
229 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); | ||
230 | if (!ctxt) return 0; | ||
231 | |||
232 | ctxt->handler.func_data = ctxt; | ||
233 | ctxt->handler.func_table = &hfuncs; | ||
234 | ctxt->ctrl.ctxt = ctxt; | ||
235 | ctxt->ctrl.detach = (void (*)(void *))decoder_detach; | ||
236 | ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; | ||
237 | ctxt->client = cp; | ||
238 | ctxt->hdw = hdw; | ||
239 | ctxt->stale_mask = (1 << ARRAY_SIZE(decoder_ops)) - 1; | ||
240 | pvr2_hdw_set_decoder(hdw,&ctxt->ctrl); | ||
241 | cp->handler = &ctxt->handler; | ||
242 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up", | ||
243 | cp->client->addr); | ||
244 | return !0; | ||
245 | } | 99 | } |
246 | 100 | ||
247 | 101 | ||
248 | |||
249 | |||
250 | /* | 102 | /* |
251 | Stuff for Emacs to see, in order to encourage consistent editing style: | 103 | Stuff for Emacs to see, in order to encourage consistent editing style: |
252 | *** Local Variables: *** | 104 | *** Local Variables: *** |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h index 4ff5b892b303..3b0bd5db602b 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h | |||
@@ -32,11 +32,8 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | 34 | ||
35 | 35 | #include "pvrusb2-hdw-internal.h" | |
36 | #include "pvrusb2-i2c-core.h" | 36 | void pvr2_saa7115_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *); |
37 | |||
38 | int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); | ||
39 | |||
40 | 37 | ||
41 | #endif /* __PVRUSB2_VIDEO_V4L_H */ | 38 | #endif /* __PVRUSB2_VIDEO_V4L_H */ |
42 | 39 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c index f6fcf0ac6118..1670aa4051ce 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c | |||
@@ -27,7 +27,6 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include "pvrusb2-wm8775.h" | 29 | #include "pvrusb2-wm8775.h" |
30 | #include "pvrusb2-i2c-cmd-v4l2.h" | ||
31 | 30 | ||
32 | 31 | ||
33 | #include "pvrusb2-hdw-internal.h" | 32 | #include "pvrusb2-hdw-internal.h" |
@@ -37,128 +36,31 @@ | |||
37 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
38 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
39 | 38 | ||
40 | struct pvr2_v4l_wm8775 { | 39 | void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
41 | struct pvr2_i2c_handler handler; | ||
42 | struct pvr2_i2c_client *client; | ||
43 | struct pvr2_hdw *hdw; | ||
44 | unsigned long stale_mask; | ||
45 | }; | ||
46 | |||
47 | |||
48 | static void set_input(struct pvr2_v4l_wm8775 *ctxt) | ||
49 | { | ||
50 | struct v4l2_routing route; | ||
51 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
52 | |||
53 | memset(&route,0,sizeof(route)); | ||
54 | |||
55 | switch(hdw->input_val) { | ||
56 | case PVR2_CVAL_INPUT_RADIO: | ||
57 | route.input = 1; | ||
58 | break; | ||
59 | default: | ||
60 | /* All other cases just use the second input */ | ||
61 | route.input = 2; | ||
62 | break; | ||
63 | } | ||
64 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d route=0x%x)", | ||
65 | hdw->input_val,route.input); | ||
66 | |||
67 | pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); | ||
68 | } | ||
69 | |||
70 | static int check_input(struct pvr2_v4l_wm8775 *ctxt) | ||
71 | { | ||
72 | struct pvr2_hdw *hdw = ctxt->hdw; | ||
73 | return hdw->input_dirty != 0; | ||
74 | } | ||
75 | |||
76 | |||
77 | struct pvr2_v4l_wm8775_ops { | ||
78 | void (*update)(struct pvr2_v4l_wm8775 *); | ||
79 | int (*check)(struct pvr2_v4l_wm8775 *); | ||
80 | }; | ||
81 | |||
82 | |||
83 | static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = { | ||
84 | { .update = set_input, .check = check_input}, | ||
85 | }; | ||
86 | |||
87 | |||
88 | static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt, | ||
89 | char *buf,unsigned int cnt) | ||
90 | { | ||
91 | return scnprintf(buf,cnt,"handler: pvrusb2-wm8775"); | ||
92 | } | ||
93 | |||
94 | |||
95 | static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt) | ||
96 | { | 40 | { |
97 | ctxt->client->handler = NULL; | 41 | if (hdw->input_dirty || hdw->force_dirty) { |
98 | kfree(ctxt); | 42 | struct v4l2_routing route; |
99 | } | 43 | |
100 | 44 | memset(&route, 0, sizeof(route)); | |
101 | 45 | ||
102 | static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt) | 46 | switch (hdw->input_val) { |
103 | { | 47 | case PVR2_CVAL_INPUT_RADIO: |
104 | unsigned long msk; | 48 | route.input = 1; |
105 | unsigned int idx; | 49 | break; |
106 | 50 | default: | |
107 | for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { | 51 | /* All other cases just use the second input */ |
108 | msk = 1 << idx; | 52 | route.input = 2; |
109 | if (ctxt->stale_mask & msk) continue; | 53 | break; |
110 | if (wm8775_ops[idx].check(ctxt)) { | ||
111 | ctxt->stale_mask |= msk; | ||
112 | } | 54 | } |
113 | } | 55 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775" |
114 | return ctxt->stale_mask != 0; | 56 | " set_input(val=%d route=0x%x)", |
115 | } | 57 | hdw->input_val, route.input); |
116 | |||
117 | |||
118 | static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt) | ||
119 | { | ||
120 | unsigned long msk; | ||
121 | unsigned int idx; | ||
122 | 58 | ||
123 | for (idx = 0; idx < ARRAY_SIZE(wm8775_ops); idx++) { | 59 | sd->ops->audio->s_routing(sd, &route); |
124 | msk = 1 << idx; | ||
125 | if (!(ctxt->stale_mask & msk)) continue; | ||
126 | ctxt->stale_mask &= ~msk; | ||
127 | wm8775_ops[idx].update(ctxt); | ||
128 | } | 60 | } |
129 | } | 61 | } |
130 | 62 | ||
131 | 63 | ||
132 | static const struct pvr2_i2c_handler_functions hfuncs = { | ||
133 | .detach = (void (*)(void *))wm8775_detach, | ||
134 | .check = (int (*)(void *))wm8775_check, | ||
135 | .update = (void (*)(void *))wm8775_update, | ||
136 | .describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe, | ||
137 | }; | ||
138 | |||
139 | |||
140 | int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) | ||
141 | { | ||
142 | struct pvr2_v4l_wm8775 *ctxt; | ||
143 | |||
144 | if (cp->handler) return 0; | ||
145 | |||
146 | ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); | ||
147 | if (!ctxt) return 0; | ||
148 | |||
149 | ctxt->handler.func_data = ctxt; | ||
150 | ctxt->handler.func_table = &hfuncs; | ||
151 | ctxt->client = cp; | ||
152 | ctxt->hdw = hdw; | ||
153 | ctxt->stale_mask = (1 << ARRAY_SIZE(wm8775_ops)) - 1; | ||
154 | cp->handler = &ctxt->handler; | ||
155 | pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up", | ||
156 | cp->client->addr); | ||
157 | return !0; | ||
158 | } | ||
159 | |||
160 | |||
161 | |||
162 | 64 | ||
163 | /* | 65 | /* |
164 | Stuff for Emacs to see, in order to encourage consistent editing style: | 66 | Stuff for Emacs to see, in order to encourage consistent editing style: |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h index 807090961255..0577bc7246fb 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h | |||
@@ -34,9 +34,9 @@ | |||
34 | 34 | ||
35 | 35 | ||
36 | 36 | ||
37 | #include "pvrusb2-i2c-core.h" | 37 | #include "pvrusb2-hdw-internal.h" |
38 | 38 | ||
39 | int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); | 39 | void pvr2_wm8775_subdev_update(struct pvr2_hdw *, struct v4l2_subdev *sd); |
40 | 40 | ||
41 | 41 | ||
42 | #endif /* __PVRUSB2_WM8775_H */ | 42 | #endif /* __PVRUSB2_WM8775_H */ |