aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-gpio.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.c324
1 files changed, 204 insertions, 120 deletions
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index 74a44844ccaf..dc2850e87a7e 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -144,22 +144,9 @@ int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
144 return 0; 144 return 0;
145} 145}
146 146
147void ivtv_gpio_init(struct ivtv *itv) 147static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
148{ 148{
149 u16 pin = 0; 149 return container_of(sd, struct ivtv, sd_gpio);
150
151 if (itv->card->xceive_pin)
152 pin = 1 << itv->card->xceive_pin;
153
154 if ((itv->card->gpio_init.direction | pin) == 0)
155 return;
156
157 IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
158 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
159
160 /* init output data then direction */
161 write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
162 write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
163} 150}
164 151
165static struct v4l2_queryctrl gpio_ctrl_mute = { 152static struct v4l2_queryctrl gpio_ctrl_mute = {
@@ -173,134 +160,231 @@ static struct v4l2_queryctrl gpio_ctrl_mute = {
173 .flags = 0, 160 .flags = 0,
174}; 161};
175 162
176int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) 163static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
177{ 164{
178 struct v4l2_tuner *tuner = arg; 165 struct ivtv *itv = sd_to_ivtv(sd);
179 struct v4l2_control *ctrl = arg;
180 struct v4l2_routing *route = arg;
181 u16 mask, data; 166 u16 mask, data;
182 167
183 switch (command) { 168 mask = itv->card->gpio_audio_freq.mask;
184 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 169 switch (freq) {
185 mask = itv->card->gpio_audio_freq.mask; 170 case 32000:
186 switch (*(u32 *)arg) { 171 data = itv->card->gpio_audio_freq.f32000;
187 case 32000: 172 break;
188 data = itv->card->gpio_audio_freq.f32000; 173 case 44100:
189 break; 174 data = itv->card->gpio_audio_freq.f44100;
190 case 44100: 175 break;
191 data = itv->card->gpio_audio_freq.f44100; 176 case 48000:
192 break; 177 default:
193 case 48000: 178 data = itv->card->gpio_audio_freq.f48000;
194 default:
195 data = itv->card->gpio_audio_freq.f48000;
196 break;
197 }
198 break; 179 break;
180 }
181 if (mask)
182 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
183 return 0;
184}
199 185
200 case VIDIOC_G_TUNER: 186static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
201 mask = itv->card->gpio_audio_detect.mask; 187{
202 if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) 188 struct ivtv *itv = sd_to_ivtv(sd);
203 tuner->rxsubchans = V4L2_TUNER_MODE_STEREO | 189 u16 mask;
204 V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; 190
205 else 191 mask = itv->card->gpio_audio_detect.mask;
206 tuner->rxsubchans = V4L2_TUNER_SUB_MONO; 192 if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
207 return 0; 193 vt->rxsubchans = V4L2_TUNER_MODE_STEREO |
194 V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
195 else
196 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
197 return 0;
198}
208 199
209 case VIDIOC_S_TUNER: 200static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
210 mask = itv->card->gpio_audio_mode.mask; 201{
211 switch (tuner->audmode) { 202 struct ivtv *itv = sd_to_ivtv(sd);
212 case V4L2_TUNER_MODE_LANG1: 203 u16 mask, data;
213 data = itv->card->gpio_audio_mode.lang1;
214 break;
215 case V4L2_TUNER_MODE_LANG2:
216 data = itv->card->gpio_audio_mode.lang2;
217 break;
218 case V4L2_TUNER_MODE_MONO:
219 data = itv->card->gpio_audio_mode.mono;
220 break;
221 case V4L2_TUNER_MODE_STEREO:
222 case V4L2_TUNER_MODE_LANG1_LANG2:
223 default:
224 data = itv->card->gpio_audio_mode.stereo;
225 break;
226 }
227 break;
228 204
229 case AUDC_SET_RADIO: 205 mask = itv->card->gpio_audio_mode.mask;
230 mask = itv->card->gpio_audio_input.mask; 206 switch (vt->audmode) {
231 data = itv->card->gpio_audio_input.radio; 207 case V4L2_TUNER_MODE_LANG1:
208 data = itv->card->gpio_audio_mode.lang1;
209 break;
210 case V4L2_TUNER_MODE_LANG2:
211 data = itv->card->gpio_audio_mode.lang2;
212 break;
213 case V4L2_TUNER_MODE_MONO:
214 data = itv->card->gpio_audio_mode.mono;
232 break; 215 break;
216 case V4L2_TUNER_MODE_STEREO:
217 case V4L2_TUNER_MODE_LANG1_LANG2:
218 default:
219 data = itv->card->gpio_audio_mode.stereo;
220 break;
221 }
222 if (mask)
223 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
224 return 0;
225}
226
227static int subdev_s_radio(struct v4l2_subdev *sd)
228{
229 struct ivtv *itv = sd_to_ivtv(sd);
230 u16 mask, data;
231
232 mask = itv->card->gpio_audio_input.mask;
233 data = itv->card->gpio_audio_input.radio;
234 if (mask)
235 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
236 return 0;
237}
233 238
234 case VIDIOC_S_STD: 239static int subdev_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
235 mask = itv->card->gpio_audio_input.mask; 240{
241 struct ivtv *itv = sd_to_ivtv(sd);
242 u16 mask, data;
243
244 mask = itv->card->gpio_audio_input.mask;
245 data = itv->card->gpio_audio_input.tuner;
246 if (mask)
247 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
248 return 0;
249}
250
251static int subdev_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
252{
253 struct ivtv *itv = sd_to_ivtv(sd);
254 u16 mask, data;
255
256 if (route->input > 2)
257 return -EINVAL;
258 mask = itv->card->gpio_audio_input.mask;
259 switch (route->input) {
260 case 0:
236 data = itv->card->gpio_audio_input.tuner; 261 data = itv->card->gpio_audio_input.tuner;
237 break; 262 break;
238 263 case 1:
239 case VIDIOC_INT_S_AUDIO_ROUTING: 264 data = itv->card->gpio_audio_input.linein;
240 if (route->input > 2) 265 break;
241 return -EINVAL; 266 case 2:
242 mask = itv->card->gpio_audio_input.mask; 267 default:
243 switch (route->input) { 268 data = itv->card->gpio_audio_input.radio;
244 case 0:
245 data = itv->card->gpio_audio_input.tuner;
246 break;
247 case 1:
248 data = itv->card->gpio_audio_input.linein;
249 break;
250 case 2:
251 default:
252 data = itv->card->gpio_audio_input.radio;
253 break;
254 }
255 break; 269 break;
270 }
271 if (mask)
272 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
273 return 0;
274}
256 275
257 case VIDIOC_G_CTRL: 276static int subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
258 if (ctrl->id != V4L2_CID_AUDIO_MUTE) 277{
259 return -EINVAL; 278 struct ivtv *itv = sd_to_ivtv(sd);
260 mask = itv->card->gpio_audio_mute.mask; 279 u16 mask, data;
261 data = itv->card->gpio_audio_mute.mute;
262 ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data;
263 return 0;
264 280
265 case VIDIOC_S_CTRL: 281 if (ctrl->id != V4L2_CID_AUDIO_MUTE)
266 if (ctrl->id != V4L2_CID_AUDIO_MUTE) 282 return -EINVAL;
267 return -EINVAL; 283 mask = itv->card->gpio_audio_mute.mask;
268 mask = itv->card->gpio_audio_mute.mask; 284 data = itv->card->gpio_audio_mute.mute;
269 data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; 285 ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data;
270 break; 286 return 0;
287}
271 288
272 case VIDIOC_QUERYCTRL: 289static int subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
273 { 290{
274 struct v4l2_queryctrl *qc = arg; 291 struct ivtv *itv = sd_to_ivtv(sd);
292 u16 mask, data;
275 293
276 if (qc->id != V4L2_CID_AUDIO_MUTE) 294 if (ctrl->id != V4L2_CID_AUDIO_MUTE)
277 return -EINVAL; 295 return -EINVAL;
278 *qc = gpio_ctrl_mute; 296 mask = itv->card->gpio_audio_mute.mask;
279 return 0; 297 data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0;
280 } 298 if (mask)
299 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
300 return 0;
301}
302
303static int subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
304{
305 if (qc->id != V4L2_CID_AUDIO_MUTE)
306 return -EINVAL;
307 *qc = gpio_ctrl_mute;
308 return 0;
309}
310
311static int subdev_log_status(struct v4l2_subdev *sd)
312{
313 struct ivtv *itv = sd_to_ivtv(sd);
281 314
282 case VIDIOC_LOG_STATUS: 315 IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
283 IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
284 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), 316 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
285 read_reg(IVTV_REG_GPIO_IN)); 317 read_reg(IVTV_REG_GPIO_IN));
286 return 0; 318 return 0;
319}
287 320
288 case VIDIOC_INT_S_VIDEO_ROUTING: 321static int subdev_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
289 if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ 322{
290 return -EINVAL; 323 struct ivtv *itv = sd_to_ivtv(sd);
291 mask = itv->card->gpio_video_input.mask; 324 u16 mask, data;
292 if (route->input == 0)
293 data = itv->card->gpio_video_input.tuner;
294 else if (route->input == 1)
295 data = itv->card->gpio_video_input.composite;
296 else
297 data = itv->card->gpio_video_input.svideo;
298 break;
299 325
300 default: 326 if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */
301 return -EINVAL; 327 return -EINVAL;
302 } 328 mask = itv->card->gpio_video_input.mask;
329 if (route->input == 0)
330 data = itv->card->gpio_video_input.tuner;
331 else if (route->input == 1)
332 data = itv->card->gpio_video_input.composite;
333 else
334 data = itv->card->gpio_video_input.svideo;
303 if (mask) 335 if (mask)
304 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); 336 write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
305 return 0; 337 return 0;
306} 338}
339
340static const struct v4l2_subdev_core_ops subdev_core_ops = {
341 .log_status = subdev_log_status,
342 .g_ctrl = subdev_g_ctrl,
343 .s_ctrl = subdev_s_ctrl,
344 .queryctrl = subdev_queryctrl,
345};
346
347static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
348 .s_std = subdev_s_std,
349 .s_radio = subdev_s_radio,
350 .g_tuner = subdev_g_tuner,
351 .s_tuner = subdev_s_tuner,
352};
353
354static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
355 .s_clock_freq = subdev_s_clock_freq,
356 .s_routing = subdev_s_audio_routing,
357};
358
359static const struct v4l2_subdev_video_ops subdev_video_ops = {
360 .s_routing = subdev_s_video_routing,
361};
362
363static const struct v4l2_subdev_ops subdev_ops = {
364 .core = &subdev_core_ops,
365 .tuner = &subdev_tuner_ops,
366 .audio = &subdev_audio_ops,
367 .video = &subdev_video_ops,
368};
369
370int ivtv_gpio_init(struct ivtv *itv)
371{
372 u16 pin = 0;
373
374 if (itv->card->xceive_pin)
375 pin = 1 << itv->card->xceive_pin;
376
377 if ((itv->card->gpio_init.direction | pin) == 0)
378 return 0;
379
380 IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
381 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
382
383 /* init output data then direction */
384 write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
385 write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
386 v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
387 snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->device.name);
388 itv->sd_gpio.grp_id = IVTV_HW_GPIO;
389 return v4l2_device_register_subdev(&itv->device, &itv->sd_gpio);
390}