diff options
Diffstat (limited to 'drivers/media/usb')
90 files changed, 11025 insertions, 768 deletions
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig index 39d824e2bb69..94d51e092db3 100644 --- a/drivers/media/usb/Kconfig +++ b/drivers/media/usb/Kconfig | |||
| @@ -27,6 +27,7 @@ source "drivers/media/usb/hdpvr/Kconfig" | |||
| 27 | source "drivers/media/usb/tlg2300/Kconfig" | 27 | source "drivers/media/usb/tlg2300/Kconfig" |
| 28 | source "drivers/media/usb/usbvision/Kconfig" | 28 | source "drivers/media/usb/usbvision/Kconfig" |
| 29 | source "drivers/media/usb/stk1160/Kconfig" | 29 | source "drivers/media/usb/stk1160/Kconfig" |
| 30 | source "drivers/media/usb/go7007/Kconfig" | ||
| 30 | endif | 31 | endif |
| 31 | 32 | ||
| 32 | if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT) | 33 | if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT) |
| @@ -52,5 +53,11 @@ if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT) | |||
| 52 | source "drivers/media/usb/em28xx/Kconfig" | 53 | source "drivers/media/usb/em28xx/Kconfig" |
| 53 | endif | 54 | endif |
| 54 | 55 | ||
| 56 | if MEDIA_SDR_SUPPORT | ||
| 57 | comment "Software defined radio USB devices" | ||
| 58 | source "drivers/media/usb/msi2500/Kconfig" | ||
| 59 | source "drivers/media/usb/airspy/Kconfig" | ||
| 60 | endif | ||
| 61 | |||
| 55 | endif #MEDIA_USB_SUPPORT | 62 | endif #MEDIA_USB_SUPPORT |
| 56 | endif #USB | 63 | endif #USB |
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile index 7ac4b143dce8..f438efffefc5 100644 --- a/drivers/media/usb/Makefile +++ b/drivers/media/usb/Makefile | |||
| @@ -9,6 +9,8 @@ obj-y += zr364xx/ stkwebcam/ s2255/ | |||
| 9 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ | 9 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ |
| 10 | obj-$(CONFIG_USB_GSPCA) += gspca/ | 10 | obj-$(CONFIG_USB_GSPCA) += gspca/ |
| 11 | obj-$(CONFIG_USB_PWC) += pwc/ | 11 | obj-$(CONFIG_USB_PWC) += pwc/ |
| 12 | obj-$(CONFIG_USB_MSI2500) += msi2500/ | ||
| 13 | obj-$(CONFIG_USB_AIRSPY) += airspy/ | ||
| 12 | obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ | 14 | obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ |
| 13 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ | 15 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ |
| 14 | obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ | 16 | obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/ |
| @@ -20,3 +22,4 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/ | |||
| 20 | obj-$(CONFIG_VIDEO_TM6000) += tm6000/ | 22 | obj-$(CONFIG_VIDEO_TM6000) += tm6000/ |
| 21 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ | 23 | obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ |
| 22 | obj-$(CONFIG_VIDEO_USBTV) += usbtv/ | 24 | obj-$(CONFIG_VIDEO_USBTV) += usbtv/ |
| 25 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ | ||
diff --git a/drivers/media/usb/airspy/Kconfig b/drivers/media/usb/airspy/Kconfig new file mode 100644 index 000000000000..10b204cf4dbc --- /dev/null +++ b/drivers/media/usb/airspy/Kconfig | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | config USB_AIRSPY | ||
| 2 | tristate "AirSpy" | ||
| 3 | depends on VIDEO_V4L2 | ||
| 4 | select VIDEOBUF2_VMALLOC | ||
| 5 | ---help--- | ||
| 6 | This is a video4linux2 driver for AirSpy SDR device. | ||
| 7 | |||
| 8 | To compile this driver as a module, choose M here: the | ||
| 9 | module will be called airspy | ||
| 10 | |||
diff --git a/drivers/media/usb/airspy/Makefile b/drivers/media/usb/airspy/Makefile new file mode 100644 index 000000000000..8d8e61c1a349 --- /dev/null +++ b/drivers/media/usb/airspy/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-$(CONFIG_USB_AIRSPY) += airspy.o | |||
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c new file mode 100644 index 000000000000..cb0e515d80ae --- /dev/null +++ b/drivers/media/usb/airspy/airspy.c | |||
| @@ -0,0 +1,1132 @@ | |||
| 1 | /* | ||
| 2 | * AirSpy SDR driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Antti Palosaari <crope@iki.fi> | ||
| 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, or | ||
| 9 | * (at your option) any later version. | ||
| 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 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/usb.h> | ||
| 20 | #include <media/v4l2-device.h> | ||
| 21 | #include <media/v4l2-ioctl.h> | ||
| 22 | #include <media/v4l2-ctrls.h> | ||
| 23 | #include <media/v4l2-event.h> | ||
| 24 | #include <media/videobuf2-vmalloc.h> | ||
| 25 | |||
| 26 | /* AirSpy USB API commands (from AirSpy Library) */ | ||
| 27 | enum { | ||
| 28 | CMD_INVALID = 0x00, | ||
| 29 | CMD_RECEIVER_MODE = 0x01, | ||
| 30 | CMD_SI5351C_WRITE = 0x02, | ||
| 31 | CMD_SI5351C_READ = 0x03, | ||
| 32 | CMD_R820T_WRITE = 0x04, | ||
| 33 | CMD_R820T_READ = 0x05, | ||
| 34 | CMD_SPIFLASH_ERASE = 0x06, | ||
| 35 | CMD_SPIFLASH_WRITE = 0x07, | ||
| 36 | CMD_SPIFLASH_READ = 0x08, | ||
| 37 | CMD_BOARD_ID_READ = 0x09, | ||
| 38 | CMD_VERSION_STRING_READ = 0x0a, | ||
| 39 | CMD_BOARD_PARTID_SERIALNO_READ = 0x0b, | ||
| 40 | CMD_SET_SAMPLE_RATE = 0x0c, | ||
| 41 | CMD_SET_FREQ = 0x0d, | ||
| 42 | CMD_SET_LNA_GAIN = 0x0e, | ||
| 43 | CMD_SET_MIXER_GAIN = 0x0f, | ||
| 44 | CMD_SET_VGA_GAIN = 0x10, | ||
| 45 | CMD_SET_LNA_AGC = 0x11, | ||
| 46 | CMD_SET_MIXER_AGC = 0x12, | ||
| 47 | CMD_SET_PACKING = 0x13, | ||
| 48 | }; | ||
| 49 | |||
| 50 | /* | ||
| 51 | * bEndpointAddress 0x81 EP 1 IN | ||
| 52 | * Transfer Type Bulk | ||
| 53 | * wMaxPacketSize 0x0200 1x 512 bytes | ||
| 54 | */ | ||
| 55 | #define MAX_BULK_BUFS (6) | ||
| 56 | #define BULK_BUFFER_SIZE (128 * 512) | ||
| 57 | |||
| 58 | static const struct v4l2_frequency_band bands[] = { | ||
| 59 | { | ||
| 60 | .tuner = 0, | ||
| 61 | .type = V4L2_TUNER_ADC, | ||
| 62 | .index = 0, | ||
| 63 | .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, | ||
| 64 | .rangelow = 20000000, | ||
| 65 | .rangehigh = 20000000, | ||
| 66 | }, | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const struct v4l2_frequency_band bands_rf[] = { | ||
| 70 | { | ||
| 71 | .tuner = 1, | ||
| 72 | .type = V4L2_TUNER_RF, | ||
| 73 | .index = 0, | ||
| 74 | .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, | ||
| 75 | .rangelow = 24000000, | ||
| 76 | .rangehigh = 1750000000, | ||
| 77 | }, | ||
| 78 | }; | ||
| 79 | |||
| 80 | /* stream formats */ | ||
| 81 | struct airspy_format { | ||
| 82 | char *name; | ||
| 83 | u32 pixelformat; | ||
| 84 | u32 buffersize; | ||
| 85 | }; | ||
| 86 | |||
| 87 | /* format descriptions for capture and preview */ | ||
| 88 | static struct airspy_format formats[] = { | ||
| 89 | { | ||
| 90 | .name = "Real U12LE", | ||
| 91 | .pixelformat = V4L2_SDR_FMT_RU12LE, | ||
| 92 | .buffersize = BULK_BUFFER_SIZE, | ||
| 93 | }, | ||
| 94 | }; | ||
| 95 | |||
| 96 | static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); | ||
| 97 | |||
| 98 | /* intermediate buffers with raw data from the USB device */ | ||
| 99 | struct airspy_frame_buf { | ||
| 100 | struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ | ||
| 101 | struct list_head list; | ||
| 102 | }; | ||
| 103 | |||
| 104 | struct airspy { | ||
| 105 | #define POWER_ON (1 << 1) | ||
| 106 | #define URB_BUF (1 << 2) | ||
| 107 | #define USB_STATE_URB_BUF (1 << 3) | ||
| 108 | unsigned long flags; | ||
| 109 | |||
| 110 | struct usb_device *udev; | ||
| 111 | struct video_device vdev; | ||
| 112 | struct v4l2_device v4l2_dev; | ||
| 113 | |||
| 114 | /* videobuf2 queue and queued buffers list */ | ||
| 115 | struct vb2_queue vb_queue; | ||
| 116 | struct list_head queued_bufs; | ||
| 117 | spinlock_t queued_bufs_lock; /* Protects queued_bufs */ | ||
| 118 | unsigned sequence; /* Buffer sequence counter */ | ||
| 119 | unsigned int vb_full; /* vb is full and packets dropped */ | ||
| 120 | |||
| 121 | /* Note if taking both locks v4l2_lock must always be locked first! */ | ||
| 122 | struct mutex v4l2_lock; /* Protects everything else */ | ||
| 123 | struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ | ||
| 124 | |||
| 125 | struct urb *urb_list[MAX_BULK_BUFS]; | ||
| 126 | int buf_num; | ||
| 127 | unsigned long buf_size; | ||
| 128 | u8 *buf_list[MAX_BULK_BUFS]; | ||
| 129 | dma_addr_t dma_addr[MAX_BULK_BUFS]; | ||
| 130 | int urbs_initialized; | ||
| 131 | int urbs_submitted; | ||
| 132 | |||
| 133 | /* USB control message buffer */ | ||
| 134 | #define BUF_SIZE 24 | ||
| 135 | u8 buf[BUF_SIZE]; | ||
| 136 | |||
| 137 | /* Current configuration */ | ||
| 138 | unsigned int f_adc; | ||
| 139 | unsigned int f_rf; | ||
| 140 | u32 pixelformat; | ||
| 141 | u32 buffersize; | ||
| 142 | |||
| 143 | /* Controls */ | ||
| 144 | struct v4l2_ctrl_handler hdl; | ||
| 145 | struct v4l2_ctrl *lna_gain_auto; | ||
| 146 | struct v4l2_ctrl *lna_gain; | ||
| 147 | struct v4l2_ctrl *mixer_gain_auto; | ||
| 148 | struct v4l2_ctrl *mixer_gain; | ||
| 149 | struct v4l2_ctrl *if_gain; | ||
| 150 | |||
| 151 | /* Sample rate calc */ | ||
| 152 | unsigned long jiffies_next; | ||
| 153 | unsigned int sample; | ||
| 154 | unsigned int sample_measured; | ||
| 155 | }; | ||
| 156 | |||
| 157 | #define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \ | ||
| 158 | char *_direction; \ | ||
| 159 | if (_t & USB_DIR_IN) \ | ||
| 160 | _direction = "<<<"; \ | ||
| 161 | else \ | ||
| 162 | _direction = ">>>"; \ | ||
| 163 | dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \ | ||
| 164 | "%s %*ph\n", __func__, _t, _r, _v & 0xff, _v >> 8, \ | ||
| 165 | _i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \ | ||
| 166 | _l, _b); \ | ||
| 167 | } | ||
| 168 | |||
| 169 | /* execute firmware command */ | ||
| 170 | static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index, | ||
| 171 | u8 *data, u16 size) | ||
| 172 | { | ||
| 173 | int ret; | ||
| 174 | unsigned int pipe; | ||
| 175 | u8 requesttype; | ||
| 176 | |||
| 177 | switch (request) { | ||
| 178 | case CMD_RECEIVER_MODE: | ||
| 179 | case CMD_SET_FREQ: | ||
| 180 | pipe = usb_sndctrlpipe(s->udev, 0); | ||
| 181 | requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT); | ||
| 182 | break; | ||
| 183 | case CMD_BOARD_ID_READ: | ||
| 184 | case CMD_VERSION_STRING_READ: | ||
| 185 | case CMD_BOARD_PARTID_SERIALNO_READ: | ||
| 186 | case CMD_SET_LNA_GAIN: | ||
| 187 | case CMD_SET_MIXER_GAIN: | ||
| 188 | case CMD_SET_VGA_GAIN: | ||
| 189 | case CMD_SET_LNA_AGC: | ||
| 190 | case CMD_SET_MIXER_AGC: | ||
| 191 | pipe = usb_rcvctrlpipe(s->udev, 0); | ||
| 192 | requesttype = (USB_TYPE_VENDOR | USB_DIR_IN); | ||
| 193 | break; | ||
| 194 | default: | ||
| 195 | dev_err(&s->udev->dev, "Unknown command %02x\n", request); | ||
| 196 | ret = -EINVAL; | ||
| 197 | goto err; | ||
| 198 | } | ||
| 199 | |||
| 200 | /* write request */ | ||
| 201 | if (!(requesttype & USB_DIR_IN)) | ||
| 202 | memcpy(s->buf, data, size); | ||
| 203 | |||
| 204 | ret = usb_control_msg(s->udev, pipe, request, requesttype, value, | ||
| 205 | index, s->buf, size, 1000); | ||
| 206 | airspy_dbg_usb_control_msg(s->udev, request, requesttype, value, | ||
| 207 | index, s->buf, size); | ||
| 208 | if (ret < 0) { | ||
| 209 | dev_err(&s->udev->dev, | ||
| 210 | "usb_control_msg() failed %d request %02x\n", | ||
| 211 | ret, request); | ||
| 212 | goto err; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* read request */ | ||
| 216 | if (requesttype & USB_DIR_IN) | ||
| 217 | memcpy(data, s->buf, size); | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | err: | ||
| 221 | return ret; | ||
| 222 | } | ||
| 223 | |||
| 224 | /* Private functions */ | ||
| 225 | static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s) | ||
| 226 | { | ||
| 227 | unsigned long flags = 0; | ||
| 228 | struct airspy_frame_buf *buf = NULL; | ||
| 229 | |||
| 230 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 231 | if (list_empty(&s->queued_bufs)) | ||
| 232 | goto leave; | ||
| 233 | |||
| 234 | buf = list_entry(s->queued_bufs.next, | ||
| 235 | struct airspy_frame_buf, list); | ||
| 236 | list_del(&buf->list); | ||
| 237 | leave: | ||
| 238 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 239 | return buf; | ||
| 240 | } | ||
| 241 | |||
| 242 | static unsigned int airspy_convert_stream(struct airspy *s, | ||
| 243 | void *dst, void *src, unsigned int src_len) | ||
| 244 | { | ||
| 245 | unsigned int dst_len; | ||
| 246 | |||
| 247 | if (s->pixelformat == V4L2_SDR_FMT_RU12LE) { | ||
| 248 | memcpy(dst, src, src_len); | ||
| 249 | dst_len = src_len; | ||
| 250 | } else { | ||
| 251 | dst_len = 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* calculate samping rate and output it in 10 seconds intervals */ | ||
| 255 | if (unlikely(time_is_before_jiffies(s->jiffies_next))) { | ||
| 256 | #define MSECS 10000UL | ||
| 257 | unsigned int samples = s->sample - s->sample_measured; | ||
| 258 | s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); | ||
| 259 | s->sample_measured = s->sample; | ||
| 260 | dev_dbg(&s->udev->dev, | ||
| 261 | "slen=%d samples=%u msecs=%lu sample rate=%lu\n", | ||
| 262 | src_len, samples, MSECS, | ||
| 263 | samples * 1000UL / MSECS); | ||
| 264 | } | ||
| 265 | |||
| 266 | /* total number of samples */ | ||
| 267 | s->sample += src_len / 2; | ||
| 268 | |||
| 269 | return dst_len; | ||
| 270 | } | ||
| 271 | |||
| 272 | /* | ||
| 273 | * This gets called for the bulk stream pipe. This is done in interrupt | ||
| 274 | * time, so it has to be fast, not crash, and not stall. Neat. | ||
| 275 | */ | ||
| 276 | static void airspy_urb_complete(struct urb *urb) | ||
| 277 | { | ||
| 278 | struct airspy *s = urb->context; | ||
| 279 | struct airspy_frame_buf *fbuf; | ||
| 280 | |||
| 281 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 282 | "%s: status=%d length=%d/%d errors=%d\n", | ||
| 283 | __func__, urb->status, urb->actual_length, | ||
| 284 | urb->transfer_buffer_length, urb->error_count); | ||
| 285 | |||
| 286 | switch (urb->status) { | ||
| 287 | case 0: /* success */ | ||
| 288 | case -ETIMEDOUT: /* NAK */ | ||
| 289 | break; | ||
| 290 | case -ECONNRESET: /* kill */ | ||
| 291 | case -ENOENT: | ||
| 292 | case -ESHUTDOWN: | ||
| 293 | return; | ||
| 294 | default: /* error */ | ||
| 295 | dev_err_ratelimited(&s->udev->dev, "URB failed %d\n", | ||
| 296 | urb->status); | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | |||
| 300 | if (likely(urb->actual_length > 0)) { | ||
| 301 | void *ptr; | ||
| 302 | unsigned int len; | ||
| 303 | /* get free framebuffer */ | ||
| 304 | fbuf = airspy_get_next_fill_buf(s); | ||
| 305 | if (unlikely(fbuf == NULL)) { | ||
| 306 | s->vb_full++; | ||
| 307 | dev_notice_ratelimited(&s->udev->dev, | ||
| 308 | "videobuf is full, %d packets dropped\n", | ||
| 309 | s->vb_full); | ||
| 310 | goto skip; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* fill framebuffer */ | ||
| 314 | ptr = vb2_plane_vaddr(&fbuf->vb, 0); | ||
| 315 | len = airspy_convert_stream(s, ptr, urb->transfer_buffer, | ||
| 316 | urb->actual_length); | ||
| 317 | vb2_set_plane_payload(&fbuf->vb, 0, len); | ||
| 318 | v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp); | ||
| 319 | fbuf->vb.v4l2_buf.sequence = s->sequence++; | ||
| 320 | vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); | ||
| 321 | } | ||
| 322 | skip: | ||
| 323 | usb_submit_urb(urb, GFP_ATOMIC); | ||
| 324 | } | ||
| 325 | |||
| 326 | static int airspy_kill_urbs(struct airspy *s) | ||
| 327 | { | ||
| 328 | int i; | ||
| 329 | |||
| 330 | for (i = s->urbs_submitted - 1; i >= 0; i--) { | ||
| 331 | dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i); | ||
| 332 | /* stop the URB */ | ||
| 333 | usb_kill_urb(s->urb_list[i]); | ||
| 334 | } | ||
| 335 | s->urbs_submitted = 0; | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | |||
| 340 | static int airspy_submit_urbs(struct airspy *s) | ||
| 341 | { | ||
| 342 | int i, ret; | ||
| 343 | |||
| 344 | for (i = 0; i < s->urbs_initialized; i++) { | ||
| 345 | dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i); | ||
| 346 | ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC); | ||
| 347 | if (ret) { | ||
| 348 | dev_err(&s->udev->dev, | ||
| 349 | "Could not submit URB no. %d - get them all back\n", | ||
| 350 | i); | ||
| 351 | airspy_kill_urbs(s); | ||
| 352 | return ret; | ||
| 353 | } | ||
| 354 | s->urbs_submitted++; | ||
| 355 | } | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | static int airspy_free_stream_bufs(struct airspy *s) | ||
| 361 | { | ||
| 362 | if (s->flags & USB_STATE_URB_BUF) { | ||
| 363 | while (s->buf_num) { | ||
| 364 | s->buf_num--; | ||
| 365 | dev_dbg(&s->udev->dev, "%s: free buf=%d\n", | ||
| 366 | __func__, s->buf_num); | ||
| 367 | usb_free_coherent(s->udev, s->buf_size, | ||
| 368 | s->buf_list[s->buf_num], | ||
| 369 | s->dma_addr[s->buf_num]); | ||
| 370 | } | ||
| 371 | } | ||
| 372 | s->flags &= ~USB_STATE_URB_BUF; | ||
| 373 | |||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | static int airspy_alloc_stream_bufs(struct airspy *s) | ||
| 378 | { | ||
| 379 | s->buf_num = 0; | ||
| 380 | s->buf_size = BULK_BUFFER_SIZE; | ||
| 381 | |||
| 382 | dev_dbg(&s->udev->dev, | ||
| 383 | "%s: all in all I will use %u bytes for streaming\n", | ||
| 384 | __func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE); | ||
| 385 | |||
| 386 | for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) { | ||
| 387 | s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev, | ||
| 388 | BULK_BUFFER_SIZE, GFP_ATOMIC, | ||
| 389 | &s->dma_addr[s->buf_num]); | ||
| 390 | if (!s->buf_list[s->buf_num]) { | ||
| 391 | dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n", | ||
| 392 | __func__, s->buf_num); | ||
| 393 | airspy_free_stream_bufs(s); | ||
| 394 | return -ENOMEM; | ||
| 395 | } | ||
| 396 | |||
| 397 | dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", | ||
| 398 | __func__, s->buf_num, | ||
| 399 | s->buf_list[s->buf_num], | ||
| 400 | (long long)s->dma_addr[s->buf_num]); | ||
| 401 | s->flags |= USB_STATE_URB_BUF; | ||
| 402 | } | ||
| 403 | |||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | static int airspy_free_urbs(struct airspy *s) | ||
| 408 | { | ||
| 409 | int i; | ||
| 410 | |||
| 411 | airspy_kill_urbs(s); | ||
| 412 | |||
| 413 | for (i = s->urbs_initialized - 1; i >= 0; i--) { | ||
| 414 | if (s->urb_list[i]) { | ||
| 415 | dev_dbg(&s->udev->dev, "%s: free urb=%d\n", | ||
| 416 | __func__, i); | ||
| 417 | /* free the URBs */ | ||
| 418 | usb_free_urb(s->urb_list[i]); | ||
| 419 | } | ||
| 420 | } | ||
| 421 | s->urbs_initialized = 0; | ||
| 422 | |||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static int airspy_alloc_urbs(struct airspy *s) | ||
| 427 | { | ||
| 428 | int i, j; | ||
| 429 | |||
| 430 | /* allocate the URBs */ | ||
| 431 | for (i = 0; i < MAX_BULK_BUFS; i++) { | ||
| 432 | dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i); | ||
| 433 | s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); | ||
| 434 | if (!s->urb_list[i]) { | ||
| 435 | dev_dbg(&s->udev->dev, "%s: failed\n", __func__); | ||
| 436 | for (j = 0; j < i; j++) | ||
| 437 | usb_free_urb(s->urb_list[j]); | ||
| 438 | return -ENOMEM; | ||
| 439 | } | ||
| 440 | usb_fill_bulk_urb(s->urb_list[i], | ||
| 441 | s->udev, | ||
| 442 | usb_rcvbulkpipe(s->udev, 0x81), | ||
| 443 | s->buf_list[i], | ||
| 444 | BULK_BUFFER_SIZE, | ||
| 445 | airspy_urb_complete, s); | ||
| 446 | |||
| 447 | s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
| 448 | s->urb_list[i]->transfer_dma = s->dma_addr[i]; | ||
| 449 | s->urbs_initialized++; | ||
| 450 | } | ||
| 451 | |||
| 452 | return 0; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Must be called with vb_queue_lock hold */ | ||
| 456 | static void airspy_cleanup_queued_bufs(struct airspy *s) | ||
| 457 | { | ||
| 458 | unsigned long flags = 0; | ||
| 459 | |||
| 460 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 461 | |||
| 462 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 463 | while (!list_empty(&s->queued_bufs)) { | ||
| 464 | struct airspy_frame_buf *buf; | ||
| 465 | buf = list_entry(s->queued_bufs.next, | ||
| 466 | struct airspy_frame_buf, list); | ||
| 467 | list_del(&buf->list); | ||
| 468 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
| 469 | } | ||
| 470 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 471 | } | ||
| 472 | |||
| 473 | /* The user yanked out the cable... */ | ||
| 474 | static void airspy_disconnect(struct usb_interface *intf) | ||
| 475 | { | ||
| 476 | struct v4l2_device *v = usb_get_intfdata(intf); | ||
| 477 | struct airspy *s = container_of(v, struct airspy, v4l2_dev); | ||
| 478 | |||
| 479 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 480 | |||
| 481 | mutex_lock(&s->vb_queue_lock); | ||
| 482 | mutex_lock(&s->v4l2_lock); | ||
| 483 | /* No need to keep the urbs around after disconnection */ | ||
| 484 | s->udev = NULL; | ||
| 485 | v4l2_device_disconnect(&s->v4l2_dev); | ||
| 486 | video_unregister_device(&s->vdev); | ||
| 487 | mutex_unlock(&s->v4l2_lock); | ||
| 488 | mutex_unlock(&s->vb_queue_lock); | ||
| 489 | |||
| 490 | v4l2_device_put(&s->v4l2_dev); | ||
| 491 | } | ||
| 492 | |||
| 493 | /* Videobuf2 operations */ | ||
| 494 | static int airspy_queue_setup(struct vb2_queue *vq, | ||
| 495 | const struct v4l2_format *fmt, unsigned int *nbuffers, | ||
| 496 | unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) | ||
| 497 | { | ||
| 498 | struct airspy *s = vb2_get_drv_priv(vq); | ||
| 499 | |||
| 500 | dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); | ||
| 501 | |||
| 502 | /* Need at least 8 buffers */ | ||
| 503 | if (vq->num_buffers + *nbuffers < 8) | ||
| 504 | *nbuffers = 8 - vq->num_buffers; | ||
| 505 | *nplanes = 1; | ||
| 506 | sizes[0] = PAGE_ALIGN(s->buffersize); | ||
| 507 | |||
| 508 | dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", | ||
| 509 | __func__, *nbuffers, sizes[0]); | ||
| 510 | return 0; | ||
| 511 | } | ||
| 512 | |||
| 513 | static void airspy_buf_queue(struct vb2_buffer *vb) | ||
| 514 | { | ||
| 515 | struct airspy *s = vb2_get_drv_priv(vb->vb2_queue); | ||
| 516 | struct airspy_frame_buf *buf = | ||
| 517 | container_of(vb, struct airspy_frame_buf, vb); | ||
| 518 | unsigned long flags = 0; | ||
| 519 | |||
| 520 | /* Check the device has not disconnected between prep and queuing */ | ||
| 521 | if (unlikely(!s->udev)) { | ||
| 522 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
| 523 | return; | ||
| 524 | } | ||
| 525 | |||
| 526 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 527 | list_add_tail(&buf->list, &s->queued_bufs); | ||
| 528 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 529 | } | ||
| 530 | |||
| 531 | static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
| 532 | { | ||
| 533 | struct airspy *s = vb2_get_drv_priv(vq); | ||
| 534 | int ret; | ||
| 535 | |||
| 536 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 537 | |||
| 538 | if (!s->udev) | ||
| 539 | return -ENODEV; | ||
| 540 | |||
| 541 | mutex_lock(&s->v4l2_lock); | ||
| 542 | |||
| 543 | set_bit(POWER_ON, &s->flags); | ||
| 544 | |||
| 545 | s->sequence = 0; | ||
| 546 | |||
| 547 | ret = airspy_alloc_stream_bufs(s); | ||
| 548 | if (ret) | ||
| 549 | goto err; | ||
| 550 | |||
| 551 | ret = airspy_alloc_urbs(s); | ||
| 552 | if (ret) | ||
| 553 | goto err; | ||
| 554 | |||
| 555 | ret = airspy_submit_urbs(s); | ||
| 556 | if (ret) | ||
| 557 | goto err; | ||
| 558 | |||
| 559 | /* start hardware streaming */ | ||
| 560 | ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0); | ||
| 561 | if (ret) | ||
| 562 | goto err; | ||
| 563 | err: | ||
| 564 | mutex_unlock(&s->v4l2_lock); | ||
| 565 | |||
| 566 | return ret; | ||
| 567 | } | ||
| 568 | |||
| 569 | static void airspy_stop_streaming(struct vb2_queue *vq) | ||
| 570 | { | ||
| 571 | struct airspy *s = vb2_get_drv_priv(vq); | ||
| 572 | |||
| 573 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 574 | |||
| 575 | mutex_lock(&s->v4l2_lock); | ||
| 576 | |||
| 577 | /* stop hardware streaming */ | ||
| 578 | airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0); | ||
| 579 | |||
| 580 | airspy_kill_urbs(s); | ||
| 581 | airspy_free_urbs(s); | ||
| 582 | airspy_free_stream_bufs(s); | ||
| 583 | |||
| 584 | airspy_cleanup_queued_bufs(s); | ||
| 585 | |||
| 586 | clear_bit(POWER_ON, &s->flags); | ||
| 587 | |||
| 588 | mutex_unlock(&s->v4l2_lock); | ||
| 589 | } | ||
| 590 | |||
| 591 | static struct vb2_ops airspy_vb2_ops = { | ||
| 592 | .queue_setup = airspy_queue_setup, | ||
| 593 | .buf_queue = airspy_buf_queue, | ||
| 594 | .start_streaming = airspy_start_streaming, | ||
| 595 | .stop_streaming = airspy_stop_streaming, | ||
| 596 | .wait_prepare = vb2_ops_wait_prepare, | ||
| 597 | .wait_finish = vb2_ops_wait_finish, | ||
| 598 | }; | ||
| 599 | |||
| 600 | static int airspy_querycap(struct file *file, void *fh, | ||
| 601 | struct v4l2_capability *cap) | ||
| 602 | { | ||
| 603 | struct airspy *s = video_drvdata(file); | ||
| 604 | |||
| 605 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 606 | |||
| 607 | strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); | ||
| 608 | strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); | ||
| 609 | usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
| 610 | cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | | ||
| 611 | V4L2_CAP_READWRITE | V4L2_CAP_TUNER; | ||
| 612 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
| 613 | |||
| 614 | return 0; | ||
| 615 | } | ||
| 616 | |||
| 617 | static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv, | ||
| 618 | struct v4l2_fmtdesc *f) | ||
| 619 | { | ||
| 620 | struct airspy *s = video_drvdata(file); | ||
| 621 | |||
| 622 | dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index); | ||
| 623 | |||
| 624 | if (f->index >= NUM_FORMATS) | ||
| 625 | return -EINVAL; | ||
| 626 | |||
| 627 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); | ||
| 628 | f->pixelformat = formats[f->index].pixelformat; | ||
| 629 | |||
| 630 | return 0; | ||
| 631 | } | ||
| 632 | |||
| 633 | static int airspy_g_fmt_sdr_cap(struct file *file, void *priv, | ||
| 634 | struct v4l2_format *f) | ||
| 635 | { | ||
| 636 | struct airspy *s = video_drvdata(file); | ||
| 637 | |||
| 638 | dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | ||
| 639 | (char *)&s->pixelformat); | ||
| 640 | |||
| 641 | f->fmt.sdr.pixelformat = s->pixelformat; | ||
| 642 | f->fmt.sdr.buffersize = s->buffersize; | ||
| 643 | memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||
| 644 | |||
| 645 | return 0; | ||
| 646 | } | ||
| 647 | |||
| 648 | static int airspy_s_fmt_sdr_cap(struct file *file, void *priv, | ||
| 649 | struct v4l2_format *f) | ||
| 650 | { | ||
| 651 | struct airspy *s = video_drvdata(file); | ||
| 652 | struct vb2_queue *q = &s->vb_queue; | ||
| 653 | int i; | ||
| 654 | |||
| 655 | dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | ||
| 656 | (char *)&f->fmt.sdr.pixelformat); | ||
| 657 | |||
| 658 | if (vb2_is_busy(q)) | ||
| 659 | return -EBUSY; | ||
| 660 | |||
| 661 | memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||
| 662 | for (i = 0; i < NUM_FORMATS; i++) { | ||
| 663 | if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { | ||
| 664 | s->pixelformat = formats[i].pixelformat; | ||
| 665 | s->buffersize = formats[i].buffersize; | ||
| 666 | f->fmt.sdr.buffersize = formats[i].buffersize; | ||
| 667 | return 0; | ||
| 668 | } | ||
| 669 | } | ||
| 670 | |||
| 671 | s->pixelformat = formats[0].pixelformat; | ||
| 672 | s->buffersize = formats[0].buffersize; | ||
| 673 | f->fmt.sdr.pixelformat = formats[0].pixelformat; | ||
| 674 | f->fmt.sdr.buffersize = formats[0].buffersize; | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | static int airspy_try_fmt_sdr_cap(struct file *file, void *priv, | ||
| 680 | struct v4l2_format *f) | ||
| 681 | { | ||
| 682 | struct airspy *s = video_drvdata(file); | ||
| 683 | int i; | ||
| 684 | |||
| 685 | dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | ||
| 686 | (char *)&f->fmt.sdr.pixelformat); | ||
| 687 | |||
| 688 | memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||
| 689 | for (i = 0; i < NUM_FORMATS; i++) { | ||
| 690 | if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { | ||
| 691 | f->fmt.sdr.buffersize = formats[i].buffersize; | ||
| 692 | return 0; | ||
| 693 | } | ||
| 694 | } | ||
| 695 | |||
| 696 | f->fmt.sdr.pixelformat = formats[0].pixelformat; | ||
| 697 | f->fmt.sdr.buffersize = formats[0].buffersize; | ||
| 698 | |||
| 699 | return 0; | ||
| 700 | } | ||
| 701 | |||
| 702 | static int airspy_s_tuner(struct file *file, void *priv, | ||
| 703 | const struct v4l2_tuner *v) | ||
| 704 | { | ||
| 705 | struct airspy *s = video_drvdata(file); | ||
| 706 | int ret; | ||
| 707 | |||
| 708 | dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index); | ||
| 709 | |||
| 710 | if (v->index == 0) | ||
| 711 | ret = 0; | ||
| 712 | else if (v->index == 1) | ||
| 713 | ret = 0; | ||
| 714 | else | ||
| 715 | ret = -EINVAL; | ||
| 716 | |||
| 717 | return ret; | ||
| 718 | } | ||
| 719 | |||
| 720 | static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) | ||
| 721 | { | ||
| 722 | struct airspy *s = video_drvdata(file); | ||
| 723 | int ret; | ||
| 724 | |||
| 725 | dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index); | ||
| 726 | |||
| 727 | if (v->index == 0) { | ||
| 728 | strlcpy(v->name, "AirSpy ADC", sizeof(v->name)); | ||
| 729 | v->type = V4L2_TUNER_ADC; | ||
| 730 | v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; | ||
| 731 | v->rangelow = bands[0].rangelow; | ||
| 732 | v->rangehigh = bands[0].rangehigh; | ||
| 733 | ret = 0; | ||
| 734 | } else if (v->index == 1) { | ||
| 735 | strlcpy(v->name, "AirSpy RF", sizeof(v->name)); | ||
| 736 | v->type = V4L2_TUNER_RF; | ||
| 737 | v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; | ||
| 738 | v->rangelow = bands_rf[0].rangelow; | ||
| 739 | v->rangehigh = bands_rf[0].rangehigh; | ||
| 740 | ret = 0; | ||
| 741 | } else { | ||
| 742 | ret = -EINVAL; | ||
| 743 | } | ||
| 744 | |||
| 745 | return ret; | ||
| 746 | } | ||
| 747 | |||
| 748 | static int airspy_g_frequency(struct file *file, void *priv, | ||
| 749 | struct v4l2_frequency *f) | ||
| 750 | { | ||
| 751 | struct airspy *s = video_drvdata(file); | ||
| 752 | int ret = 0; | ||
| 753 | dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", | ||
| 754 | __func__, f->tuner, f->type); | ||
| 755 | |||
| 756 | if (f->tuner == 0) { | ||
| 757 | f->type = V4L2_TUNER_ADC; | ||
| 758 | f->frequency = s->f_adc; | ||
| 759 | ret = 0; | ||
| 760 | } else if (f->tuner == 1) { | ||
| 761 | f->type = V4L2_TUNER_RF; | ||
| 762 | f->frequency = s->f_rf; | ||
| 763 | } else { | ||
| 764 | ret = -EINVAL; | ||
| 765 | } | ||
| 766 | |||
| 767 | return ret; | ||
| 768 | } | ||
| 769 | |||
| 770 | static int airspy_s_frequency(struct file *file, void *priv, | ||
| 771 | const struct v4l2_frequency *f) | ||
| 772 | { | ||
| 773 | struct airspy *s = video_drvdata(file); | ||
| 774 | int ret; | ||
| 775 | u8 buf[4]; | ||
| 776 | |||
| 777 | dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n", | ||
| 778 | __func__, f->tuner, f->type, f->frequency); | ||
| 779 | |||
| 780 | if (f->tuner == 0) { | ||
| 781 | s->f_adc = clamp_t(unsigned int, f->frequency, | ||
| 782 | bands[0].rangelow, | ||
| 783 | bands[0].rangehigh); | ||
| 784 | dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n", | ||
| 785 | __func__, s->f_adc); | ||
| 786 | ret = 0; | ||
| 787 | } else if (f->tuner == 1) { | ||
| 788 | s->f_rf = clamp_t(unsigned int, f->frequency, | ||
| 789 | bands_rf[0].rangelow, | ||
| 790 | bands_rf[0].rangehigh); | ||
| 791 | dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n", | ||
| 792 | __func__, s->f_rf); | ||
| 793 | buf[0] = (s->f_rf >> 0) & 0xff; | ||
| 794 | buf[1] = (s->f_rf >> 8) & 0xff; | ||
| 795 | buf[2] = (s->f_rf >> 16) & 0xff; | ||
| 796 | buf[3] = (s->f_rf >> 24) & 0xff; | ||
| 797 | ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4); | ||
| 798 | } else { | ||
| 799 | ret = -EINVAL; | ||
| 800 | } | ||
| 801 | |||
| 802 | return ret; | ||
| 803 | } | ||
| 804 | |||
| 805 | static int airspy_enum_freq_bands(struct file *file, void *priv, | ||
| 806 | struct v4l2_frequency_band *band) | ||
| 807 | { | ||
| 808 | struct airspy *s = video_drvdata(file); | ||
| 809 | int ret; | ||
| 810 | dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n", | ||
| 811 | __func__, band->tuner, band->type, band->index); | ||
| 812 | |||
| 813 | if (band->tuner == 0) { | ||
| 814 | if (band->index >= ARRAY_SIZE(bands)) { | ||
| 815 | ret = -EINVAL; | ||
| 816 | } else { | ||
| 817 | *band = bands[band->index]; | ||
| 818 | ret = 0; | ||
| 819 | } | ||
| 820 | } else if (band->tuner == 1) { | ||
| 821 | if (band->index >= ARRAY_SIZE(bands_rf)) { | ||
| 822 | ret = -EINVAL; | ||
| 823 | } else { | ||
| 824 | *band = bands_rf[band->index]; | ||
| 825 | ret = 0; | ||
| 826 | } | ||
| 827 | } else { | ||
| 828 | ret = -EINVAL; | ||
| 829 | } | ||
| 830 | |||
| 831 | return ret; | ||
| 832 | } | ||
| 833 | |||
| 834 | static const struct v4l2_ioctl_ops airspy_ioctl_ops = { | ||
| 835 | .vidioc_querycap = airspy_querycap, | ||
| 836 | |||
| 837 | .vidioc_enum_fmt_sdr_cap = airspy_enum_fmt_sdr_cap, | ||
| 838 | .vidioc_g_fmt_sdr_cap = airspy_g_fmt_sdr_cap, | ||
| 839 | .vidioc_s_fmt_sdr_cap = airspy_s_fmt_sdr_cap, | ||
| 840 | .vidioc_try_fmt_sdr_cap = airspy_try_fmt_sdr_cap, | ||
| 841 | |||
| 842 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | ||
| 843 | .vidioc_create_bufs = vb2_ioctl_create_bufs, | ||
| 844 | .vidioc_prepare_buf = vb2_ioctl_prepare_buf, | ||
| 845 | .vidioc_querybuf = vb2_ioctl_querybuf, | ||
| 846 | .vidioc_qbuf = vb2_ioctl_qbuf, | ||
| 847 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | ||
| 848 | |||
| 849 | .vidioc_streamon = vb2_ioctl_streamon, | ||
| 850 | .vidioc_streamoff = vb2_ioctl_streamoff, | ||
| 851 | |||
| 852 | .vidioc_g_tuner = airspy_g_tuner, | ||
| 853 | .vidioc_s_tuner = airspy_s_tuner, | ||
| 854 | |||
| 855 | .vidioc_g_frequency = airspy_g_frequency, | ||
| 856 | .vidioc_s_frequency = airspy_s_frequency, | ||
| 857 | .vidioc_enum_freq_bands = airspy_enum_freq_bands, | ||
| 858 | |||
| 859 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
| 860 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
| 861 | .vidioc_log_status = v4l2_ctrl_log_status, | ||
| 862 | }; | ||
| 863 | |||
| 864 | static const struct v4l2_file_operations airspy_fops = { | ||
| 865 | .owner = THIS_MODULE, | ||
| 866 | .open = v4l2_fh_open, | ||
| 867 | .release = vb2_fop_release, | ||
| 868 | .read = vb2_fop_read, | ||
| 869 | .poll = vb2_fop_poll, | ||
| 870 | .mmap = vb2_fop_mmap, | ||
| 871 | .unlocked_ioctl = video_ioctl2, | ||
| 872 | }; | ||
| 873 | |||
| 874 | static struct video_device airspy_template = { | ||
| 875 | .name = "AirSpy SDR", | ||
| 876 | .release = video_device_release_empty, | ||
| 877 | .fops = &airspy_fops, | ||
| 878 | .ioctl_ops = &airspy_ioctl_ops, | ||
| 879 | }; | ||
| 880 | |||
| 881 | static void airspy_video_release(struct v4l2_device *v) | ||
| 882 | { | ||
| 883 | struct airspy *s = container_of(v, struct airspy, v4l2_dev); | ||
| 884 | |||
| 885 | v4l2_ctrl_handler_free(&s->hdl); | ||
| 886 | v4l2_device_unregister(&s->v4l2_dev); | ||
| 887 | kfree(s); | ||
| 888 | } | ||
| 889 | |||
| 890 | static int airspy_set_lna_gain(struct airspy *s) | ||
| 891 | { | ||
| 892 | int ret; | ||
| 893 | u8 u8tmp; | ||
| 894 | |||
| 895 | dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n", | ||
| 896 | __func__, s->lna_gain_auto->cur.val, | ||
| 897 | s->lna_gain_auto->val, s->lna_gain->cur.val, | ||
| 898 | s->lna_gain->val); | ||
| 899 | |||
| 900 | ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val, | ||
| 901 | &u8tmp, 1); | ||
| 902 | if (ret) | ||
| 903 | goto err; | ||
| 904 | |||
| 905 | if (s->lna_gain_auto->val == false) { | ||
| 906 | ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val, | ||
| 907 | &u8tmp, 1); | ||
| 908 | if (ret) | ||
| 909 | goto err; | ||
| 910 | } | ||
| 911 | err: | ||
| 912 | if (ret) | ||
| 913 | dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
| 914 | |||
| 915 | return ret; | ||
| 916 | } | ||
| 917 | |||
| 918 | static int airspy_set_mixer_gain(struct airspy *s) | ||
| 919 | { | ||
| 920 | int ret; | ||
| 921 | u8 u8tmp; | ||
| 922 | |||
| 923 | dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n", | ||
| 924 | __func__, s->mixer_gain_auto->cur.val, | ||
| 925 | s->mixer_gain_auto->val, s->mixer_gain->cur.val, | ||
| 926 | s->mixer_gain->val); | ||
| 927 | |||
| 928 | ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val, | ||
| 929 | &u8tmp, 1); | ||
| 930 | if (ret) | ||
| 931 | goto err; | ||
| 932 | |||
| 933 | if (s->mixer_gain_auto->val == false) { | ||
| 934 | ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0, | ||
| 935 | s->mixer_gain->val, &u8tmp, 1); | ||
| 936 | if (ret) | ||
| 937 | goto err; | ||
| 938 | } | ||
| 939 | err: | ||
| 940 | if (ret) | ||
| 941 | dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
| 942 | |||
| 943 | return ret; | ||
| 944 | } | ||
| 945 | |||
| 946 | static int airspy_set_if_gain(struct airspy *s) | ||
| 947 | { | ||
| 948 | int ret; | ||
| 949 | u8 u8tmp; | ||
| 950 | |||
| 951 | dev_dbg(&s->udev->dev, "%s: val=%d->%d\n", | ||
| 952 | __func__, s->if_gain->cur.val, s->if_gain->val); | ||
| 953 | |||
| 954 | ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val, | ||
| 955 | &u8tmp, 1); | ||
| 956 | if (ret) | ||
| 957 | goto err; | ||
| 958 | err: | ||
| 959 | if (ret) | ||
| 960 | dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret); | ||
| 961 | |||
| 962 | return ret; | ||
| 963 | } | ||
| 964 | |||
| 965 | static int airspy_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 966 | { | ||
| 967 | struct airspy *s = container_of(ctrl->handler, struct airspy, hdl); | ||
| 968 | int ret; | ||
| 969 | |||
| 970 | switch (ctrl->id) { | ||
| 971 | case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO: | ||
| 972 | case V4L2_CID_RF_TUNER_LNA_GAIN: | ||
| 973 | ret = airspy_set_lna_gain(s); | ||
| 974 | break; | ||
| 975 | case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO: | ||
| 976 | case V4L2_CID_RF_TUNER_MIXER_GAIN: | ||
| 977 | ret = airspy_set_mixer_gain(s); | ||
| 978 | break; | ||
| 979 | case V4L2_CID_RF_TUNER_IF_GAIN: | ||
| 980 | ret = airspy_set_if_gain(s); | ||
| 981 | break; | ||
| 982 | default: | ||
| 983 | dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n", | ||
| 984 | __func__, ctrl->id, ctrl->name); | ||
| 985 | ret = -EINVAL; | ||
| 986 | } | ||
| 987 | |||
| 988 | return ret; | ||
| 989 | } | ||
| 990 | |||
| 991 | static const struct v4l2_ctrl_ops airspy_ctrl_ops = { | ||
| 992 | .s_ctrl = airspy_s_ctrl, | ||
| 993 | }; | ||
| 994 | |||
| 995 | static int airspy_probe(struct usb_interface *intf, | ||
| 996 | const struct usb_device_id *id) | ||
| 997 | { | ||
| 998 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 999 | struct airspy *s = NULL; | ||
| 1000 | int ret; | ||
| 1001 | u8 u8tmp, buf[BUF_SIZE]; | ||
| 1002 | |||
| 1003 | s = kzalloc(sizeof(struct airspy), GFP_KERNEL); | ||
| 1004 | if (s == NULL) { | ||
| 1005 | dev_err(&udev->dev, | ||
| 1006 | "Could not allocate memory for airspy state\n"); | ||
| 1007 | return -ENOMEM; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | mutex_init(&s->v4l2_lock); | ||
| 1011 | mutex_init(&s->vb_queue_lock); | ||
| 1012 | spin_lock_init(&s->queued_bufs_lock); | ||
| 1013 | INIT_LIST_HEAD(&s->queued_bufs); | ||
| 1014 | s->udev = udev; | ||
| 1015 | s->f_adc = bands[0].rangelow; | ||
| 1016 | s->f_rf = bands_rf[0].rangelow; | ||
| 1017 | s->pixelformat = formats[0].pixelformat; | ||
| 1018 | s->buffersize = formats[0].buffersize; | ||
| 1019 | |||
| 1020 | /* Detect device */ | ||
| 1021 | ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1); | ||
| 1022 | if (ret == 0) | ||
| 1023 | ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0, | ||
| 1024 | buf, BUF_SIZE); | ||
| 1025 | if (ret) { | ||
| 1026 | dev_err(&s->udev->dev, "Could not detect board\n"); | ||
| 1027 | goto err_free_mem; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | buf[BUF_SIZE - 1] = '\0'; | ||
| 1031 | |||
| 1032 | dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp); | ||
| 1033 | dev_info(&s->udev->dev, "Firmware version: %s\n", buf); | ||
| 1034 | |||
| 1035 | /* Init videobuf2 queue structure */ | ||
| 1036 | s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; | ||
| 1037 | s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; | ||
| 1038 | s->vb_queue.drv_priv = s; | ||
| 1039 | s->vb_queue.buf_struct_size = sizeof(struct airspy_frame_buf); | ||
| 1040 | s->vb_queue.ops = &airspy_vb2_ops; | ||
| 1041 | s->vb_queue.mem_ops = &vb2_vmalloc_memops; | ||
| 1042 | s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
| 1043 | ret = vb2_queue_init(&s->vb_queue); | ||
| 1044 | if (ret) { | ||
| 1045 | dev_err(&s->udev->dev, "Could not initialize vb2 queue\n"); | ||
| 1046 | goto err_free_mem; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | /* Init video_device structure */ | ||
| 1050 | s->vdev = airspy_template; | ||
| 1051 | s->vdev.queue = &s->vb_queue; | ||
| 1052 | s->vdev.queue->lock = &s->vb_queue_lock; | ||
| 1053 | video_set_drvdata(&s->vdev, s); | ||
| 1054 | |||
| 1055 | /* Register the v4l2_device structure */ | ||
| 1056 | s->v4l2_dev.release = airspy_video_release; | ||
| 1057 | ret = v4l2_device_register(&intf->dev, &s->v4l2_dev); | ||
| 1058 | if (ret) { | ||
| 1059 | dev_err(&s->udev->dev, | ||
| 1060 | "Failed to register v4l2-device (%d)\n", ret); | ||
| 1061 | goto err_free_mem; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | /* Register controls */ | ||
| 1065 | v4l2_ctrl_handler_init(&s->hdl, 5); | ||
| 1066 | s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops, | ||
| 1067 | V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0); | ||
| 1068 | s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops, | ||
| 1069 | V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8); | ||
| 1070 | v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false); | ||
| 1071 | s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops, | ||
| 1072 | V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0); | ||
| 1073 | s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops, | ||
| 1074 | V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8); | ||
| 1075 | v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false); | ||
| 1076 | s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops, | ||
| 1077 | V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0); | ||
| 1078 | if (s->hdl.error) { | ||
| 1079 | ret = s->hdl.error; | ||
| 1080 | dev_err(&s->udev->dev, "Could not initialize controls\n"); | ||
| 1081 | goto err_free_controls; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | v4l2_ctrl_handler_setup(&s->hdl); | ||
| 1085 | |||
| 1086 | s->v4l2_dev.ctrl_handler = &s->hdl; | ||
| 1087 | s->vdev.v4l2_dev = &s->v4l2_dev; | ||
| 1088 | s->vdev.lock = &s->v4l2_lock; | ||
| 1089 | |||
| 1090 | ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1); | ||
| 1091 | if (ret) { | ||
| 1092 | dev_err(&s->udev->dev, | ||
| 1093 | "Failed to register as video device (%d)\n", | ||
| 1094 | ret); | ||
| 1095 | goto err_unregister_v4l2_dev; | ||
| 1096 | } | ||
| 1097 | dev_info(&s->udev->dev, "Registered as %s\n", | ||
| 1098 | video_device_node_name(&s->vdev)); | ||
| 1099 | dev_notice(&s->udev->dev, | ||
| 1100 | "%s: SDR API is still slightly experimental and functionality changes may follow\n", | ||
| 1101 | KBUILD_MODNAME); | ||
| 1102 | return 0; | ||
| 1103 | |||
| 1104 | err_free_controls: | ||
| 1105 | v4l2_ctrl_handler_free(&s->hdl); | ||
| 1106 | err_unregister_v4l2_dev: | ||
| 1107 | v4l2_device_unregister(&s->v4l2_dev); | ||
| 1108 | err_free_mem: | ||
| 1109 | kfree(s); | ||
| 1110 | return ret; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | /* USB device ID list */ | ||
| 1114 | static struct usb_device_id airspy_id_table[] = { | ||
| 1115 | { USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */ | ||
| 1116 | { } | ||
| 1117 | }; | ||
| 1118 | MODULE_DEVICE_TABLE(usb, airspy_id_table); | ||
| 1119 | |||
| 1120 | /* USB subsystem interface */ | ||
| 1121 | static struct usb_driver airspy_driver = { | ||
| 1122 | .name = KBUILD_MODNAME, | ||
| 1123 | .probe = airspy_probe, | ||
| 1124 | .disconnect = airspy_disconnect, | ||
| 1125 | .id_table = airspy_id_table, | ||
| 1126 | }; | ||
| 1127 | |||
| 1128 | module_usb_driver(airspy_driver); | ||
| 1129 | |||
| 1130 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 1131 | MODULE_DESCRIPTION("AirSpy SDR"); | ||
| 1132 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig index 953a37c613b1..1d410ac8f9a8 100644 --- a/drivers/media/usb/au0828/Kconfig +++ b/drivers/media/usb/au0828/Kconfig | |||
| @@ -20,9 +20,17 @@ config VIDEO_AU0828_V4L2 | |||
| 20 | bool "Auvitek AU0828 v4l2 analog video support" | 20 | bool "Auvitek AU0828 v4l2 analog video support" |
| 21 | depends on VIDEO_AU0828 && VIDEO_V4L2 | 21 | depends on VIDEO_AU0828 && VIDEO_V4L2 |
| 22 | select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT | 22 | select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT |
| 23 | select VIDEO_TUNER | ||
| 23 | default y | 24 | default y |
| 24 | ---help--- | 25 | ---help--- |
| 25 | This is a video4linux driver for Auvitek's USB device. | 26 | This is a video4linux driver for Auvitek's USB device. |
| 26 | 27 | ||
| 27 | Choose Y here to include support for v4l2 analog video | 28 | Choose Y here to include support for v4l2 analog video |
| 28 | capture within the au0828 driver. | 29 | capture within the au0828 driver. |
| 30 | |||
| 31 | config VIDEO_AU0828_RC | ||
| 32 | bool "AU0828 Remote Controller support" | ||
| 33 | depends on RC_CORE | ||
| 34 | depends on VIDEO_AU0828 | ||
| 35 | ---help--- | ||
| 36 | Enables Remote Controller support on au0828 driver. | ||
diff --git a/drivers/media/usb/au0828/Makefile b/drivers/media/usb/au0828/Makefile index be3bdf698022..3dc7539a5c4e 100644 --- a/drivers/media/usb/au0828/Makefile +++ b/drivers/media/usb/au0828/Makefile | |||
| @@ -4,6 +4,10 @@ ifeq ($(CONFIG_VIDEO_AU0828_V4L2),y) | |||
| 4 | au0828-objs += au0828-video.o au0828-vbi.o | 4 | au0828-objs += au0828-video.o au0828-vbi.o |
| 5 | endif | 5 | endif |
| 6 | 6 | ||
| 7 | ifeq ($(CONFIG_VIDEO_AU0828_RC),y) | ||
| 8 | au0828-objs += au0828-input.o | ||
| 9 | endif | ||
| 10 | |||
| 7 | obj-$(CONFIG_VIDEO_AU0828) += au0828.o | 11 | obj-$(CONFIG_VIDEO_AU0828) += au0828.o |
| 8 | 12 | ||
| 9 | ccflags-y += -Idrivers/media/tuners | 13 | ccflags-y += -Idrivers/media/tuners |
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index 7fdadf9bc90b..2c6b7da137ed 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c | |||
| @@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = { | |||
| 46 | .name = "Hauppauge HVR850", | 46 | .name = "Hauppauge HVR850", |
| 47 | .tuner_type = TUNER_XC5000, | 47 | .tuner_type = TUNER_XC5000, |
| 48 | .tuner_addr = 0x61, | 48 | .tuner_addr = 0x61, |
| 49 | .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, | 49 | .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, |
| 50 | .input = { | 50 | .input = { |
| 51 | { | 51 | { |
| 52 | .type = AU0828_VMUX_TELEVISION, | 52 | .type = AU0828_VMUX_TELEVISION, |
| @@ -71,13 +71,14 @@ struct au0828_board au0828_boards[] = { | |||
| 71 | .name = "Hauppauge HVR950Q", | 71 | .name = "Hauppauge HVR950Q", |
| 72 | .tuner_type = TUNER_XC5000, | 72 | .tuner_type = TUNER_XC5000, |
| 73 | .tuner_addr = 0x61, | 73 | .tuner_addr = 0x61, |
| 74 | .has_ir_i2c = 1, | ||
| 74 | /* The au0828 hardware i2c implementation does not properly | 75 | /* The au0828 hardware i2c implementation does not properly |
| 75 | support the xc5000's i2c clock stretching. So we need to | 76 | support the xc5000's i2c clock stretching. So we need to |
| 76 | lower the clock frequency enough where the 15us clock | 77 | lower the clock frequency enough where the 15us clock |
| 77 | stretch fits inside of a normal clock cycle, or else the | 78 | stretch fits inside of a normal clock cycle, or else the |
| 78 | au0828 fails to set the STOP bit. A 30 KHz clock puts the | 79 | au0828 fails to set the STOP bit. A 30 KHz clock puts the |
| 79 | clock pulse width at 18us */ | 80 | clock pulse width at 18us */ |
| 80 | .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, | 81 | .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, |
| 81 | .input = { | 82 | .input = { |
| 82 | { | 83 | { |
| 83 | .type = AU0828_VMUX_TELEVISION, | 84 | .type = AU0828_VMUX_TELEVISION, |
| @@ -108,7 +109,7 @@ struct au0828_board au0828_boards[] = { | |||
| 108 | .name = "DViCO FusionHDTV USB", | 109 | .name = "DViCO FusionHDTV USB", |
| 109 | .tuner_type = UNSET, | 110 | .tuner_type = UNSET, |
| 110 | .tuner_addr = ADDR_UNSET, | 111 | .tuner_addr = ADDR_UNSET, |
| 111 | .i2c_clk_divider = AU0828_I2C_CLK_20KHZ, | 112 | .i2c_clk_divider = AU0828_I2C_CLK_250KHZ, |
| 112 | }, | 113 | }, |
| 113 | [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { | 114 | [AU0828_BOARD_HAUPPAUGE_WOODBURY] = { |
| 114 | .name = "Hauppauge Woodbury", | 115 | .name = "Hauppauge Woodbury", |
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index ab45a6f9dcc9..56025e689442 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c | |||
| @@ -32,10 +32,12 @@ | |||
| 32 | * 2 = USB handling | 32 | * 2 = USB handling |
| 33 | * 4 = I2C related | 33 | * 4 = I2C related |
| 34 | * 8 = Bridge related | 34 | * 8 = Bridge related |
| 35 | * 16 = IR related | ||
| 35 | */ | 36 | */ |
| 36 | int au0828_debug; | 37 | int au0828_debug; |
| 37 | module_param_named(debug, au0828_debug, int, 0644); | 38 | module_param_named(debug, au0828_debug, int, 0644); |
| 38 | MODULE_PARM_DESC(debug, "enable debug messages"); | 39 | MODULE_PARM_DESC(debug, |
| 40 | "set debug bitmask: 1=general, 2=USB, 4=I2C, 8=bridge, 16=IR"); | ||
| 39 | 41 | ||
| 40 | static unsigned int disable_usb_speed_check; | 42 | static unsigned int disable_usb_speed_check; |
| 41 | module_param(disable_usb_speed_check, int, 0444); | 43 | module_param(disable_usb_speed_check, int, 0444); |
| @@ -151,6 +153,9 @@ static void au0828_usb_disconnect(struct usb_interface *interface) | |||
| 151 | 153 | ||
| 152 | dprintk(1, "%s()\n", __func__); | 154 | dprintk(1, "%s()\n", __func__); |
| 153 | 155 | ||
| 156 | #ifdef CONFIG_VIDEO_AU0828_RC | ||
| 157 | au0828_rc_unregister(dev); | ||
| 158 | #endif | ||
| 154 | /* Digital TV */ | 159 | /* Digital TV */ |
| 155 | au0828_dvb_unregister(dev); | 160 | au0828_dvb_unregister(dev); |
| 156 | 161 | ||
| @@ -261,9 +266,15 @@ static int au0828_usb_probe(struct usb_interface *interface, | |||
| 261 | pr_err("%s() au0282_dev_register failed\n", | 266 | pr_err("%s() au0282_dev_register failed\n", |
| 262 | __func__); | 267 | __func__); |
| 263 | 268 | ||
| 269 | #ifdef CONFIG_VIDEO_AU0828_RC | ||
| 270 | /* Remote controller */ | ||
| 271 | au0828_rc_register(dev); | ||
| 272 | #endif | ||
| 264 | 273 | ||
| 265 | /* Store the pointer to the au0828_dev so it can be accessed in | 274 | /* |
| 266 | au0828_usb_disconnect */ | 275 | * Store the pointer to the au0828_dev so it can be accessed in |
| 276 | * au0828_usb_disconnect | ||
| 277 | */ | ||
| 267 | usb_set_intfdata(interface, dev); | 278 | usb_set_intfdata(interface, dev); |
| 268 | 279 | ||
| 269 | printk(KERN_INFO "Registered device AU0828 [%s]\n", | 280 | printk(KERN_INFO "Registered device AU0828 [%s]\n", |
| @@ -279,6 +290,8 @@ static struct usb_driver au0828_usb_driver = { | |||
| 279 | .probe = au0828_usb_probe, | 290 | .probe = au0828_usb_probe, |
| 280 | .disconnect = au0828_usb_disconnect, | 291 | .disconnect = au0828_usb_disconnect, |
| 281 | .id_table = au0828_usb_id_table, | 292 | .id_table = au0828_usb_id_table, |
| 293 | |||
| 294 | /* FIXME: Add suspend and resume functions */ | ||
| 282 | }; | 295 | }; |
| 283 | 296 | ||
| 284 | static int __init au0828_init(void) | 297 | static int __init au0828_init(void) |
| @@ -298,6 +311,10 @@ static int __init au0828_init(void) | |||
| 298 | printk(KERN_INFO "%s() Bridge Debugging is enabled\n", | 311 | printk(KERN_INFO "%s() Bridge Debugging is enabled\n", |
| 299 | __func__); | 312 | __func__); |
| 300 | 313 | ||
| 314 | if (au0828_debug & 16) | ||
| 315 | printk(KERN_INFO "%s() IR Debugging is enabled\n", | ||
| 316 | __func__); | ||
| 317 | |||
| 301 | printk(KERN_INFO "au0828 driver loaded\n"); | 318 | printk(KERN_INFO "au0828 driver loaded\n"); |
| 302 | 319 | ||
| 303 | ret = usb_register(&au0828_usb_driver); | 320 | ret = usb_register(&au0828_usb_driver); |
| @@ -318,4 +335,4 @@ module_exit(au0828_exit); | |||
| 318 | MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); | 335 | MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products"); |
| 319 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); | 336 | MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>"); |
| 320 | MODULE_LICENSE("GPL"); | 337 | MODULE_LICENSE("GPL"); |
| 321 | MODULE_VERSION("0.0.2"); | 338 | MODULE_VERSION("0.0.3"); |
diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c index 17ec3651b10e..daaeaf1b089c 100644 --- a/drivers/media/usb/au0828/au0828-i2c.c +++ b/drivers/media/usb/au0828/au0828-i2c.c | |||
| @@ -141,25 +141,27 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, | |||
| 141 | { | 141 | { |
| 142 | int i, strobe = 0; | 142 | int i, strobe = 0; |
| 143 | struct au0828_dev *dev = i2c_adap->algo_data; | 143 | struct au0828_dev *dev = i2c_adap->algo_data; |
| 144 | u8 i2c_speed = dev->board.i2c_clk_divider; | ||
| 144 | 145 | ||
| 145 | dprintk(4, "%s()\n", __func__); | 146 | dprintk(4, "%s()\n", __func__); |
| 146 | 147 | ||
| 147 | au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); | 148 | au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); |
| 148 | 149 | ||
| 149 | /* Set the I2C clock */ | ||
| 150 | if (((dev->board.tuner_type == TUNER_XC5000) || | 150 | if (((dev->board.tuner_type == TUNER_XC5000) || |
| 151 | (dev->board.tuner_type == TUNER_XC5000C)) && | 151 | (dev->board.tuner_type == TUNER_XC5000C)) && |
| 152 | (dev->board.tuner_addr == msg->addr) && | 152 | (dev->board.tuner_addr == msg->addr)) { |
| 153 | (msg->len == 64)) { | 153 | /* |
| 154 | /* Hack to speed up firmware load. The xc5000 lets us do up | 154 | * Due to I2C clock stretch, we need to use a lower speed |
| 155 | to 400 KHz when in firmware download mode */ | 155 | * on xc5000 for commands. However, firmware transfer can |
| 156 | au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, | 156 | * speed up to 400 KHz. |
| 157 | AU0828_I2C_CLK_250KHZ); | 157 | */ |
| 158 | } else { | 158 | if (msg->len == 64) |
| 159 | /* Use the i2c clock speed in the board configuration */ | 159 | i2c_speed = AU0828_I2C_CLK_250KHZ; |
| 160 | au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, | 160 | else |
| 161 | dev->board.i2c_clk_divider); | 161 | i2c_speed = AU0828_I2C_CLK_20KHZ; |
| 162 | } | 162 | } |
| 163 | /* Set the I2C clock */ | ||
| 164 | au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed); | ||
| 163 | 165 | ||
| 164 | /* Hardware needs 8 bit addresses */ | 166 | /* Hardware needs 8 bit addresses */ |
| 165 | au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); | 167 | au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); |
| @@ -228,15 +230,24 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, | |||
| 228 | const struct i2c_msg *msg, int joined) | 230 | const struct i2c_msg *msg, int joined) |
| 229 | { | 231 | { |
| 230 | struct au0828_dev *dev = i2c_adap->algo_data; | 232 | struct au0828_dev *dev = i2c_adap->algo_data; |
| 233 | u8 i2c_speed = dev->board.i2c_clk_divider; | ||
| 231 | int i; | 234 | int i; |
| 232 | 235 | ||
| 233 | dprintk(4, "%s()\n", __func__); | 236 | dprintk(4, "%s()\n", __func__); |
| 234 | 237 | ||
| 235 | au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); | 238 | au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01); |
| 236 | 239 | ||
| 240 | /* | ||
| 241 | * Due to xc5000c clock stretch, we cannot use full speed at | ||
| 242 | * readings from xc5000, as otherwise they'll fail. | ||
| 243 | */ | ||
| 244 | if (((dev->board.tuner_type == TUNER_XC5000) || | ||
| 245 | (dev->board.tuner_type == TUNER_XC5000C)) && | ||
| 246 | (dev->board.tuner_addr == msg->addr)) | ||
| 247 | i2c_speed = AU0828_I2C_CLK_20KHZ; | ||
| 248 | |||
| 237 | /* Set the I2C clock */ | 249 | /* Set the I2C clock */ |
| 238 | au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, | 250 | au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed); |
| 239 | dev->board.i2c_clk_divider); | ||
| 240 | 251 | ||
| 241 | /* Hardware needs 8 bit addresses */ | 252 | /* Hardware needs 8 bit addresses */ |
| 242 | au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); | 253 | au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1); |
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c new file mode 100644 index 000000000000..fd0d3a90ce7d --- /dev/null +++ b/drivers/media/usb/au0828/au0828-input.c | |||
| @@ -0,0 +1,386 @@ | |||
| 1 | /* | ||
| 2 | handle au0828 IR remotes via linux kernel input layer. | ||
| 3 | |||
| 4 | Copyright (C) 2014 Mauro Carvalho Chehab <mchehab@samsung.com> | ||
| 5 | Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||
| 6 | |||
| 7 | Based on em28xx-input.c. | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/delay.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/usb.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <media/rc-core.h> | ||
| 27 | |||
| 28 | #include "au0828.h" | ||
| 29 | |||
| 30 | struct au0828_rc { | ||
| 31 | struct au0828_dev *dev; | ||
| 32 | struct rc_dev *rc; | ||
| 33 | char name[32]; | ||
| 34 | char phys[32]; | ||
| 35 | |||
| 36 | /* poll decoder */ | ||
| 37 | int polling; | ||
| 38 | struct delayed_work work; | ||
| 39 | |||
| 40 | /* i2c slave address of external device (if used) */ | ||
| 41 | u16 i2c_dev_addr; | ||
| 42 | |||
| 43 | int (*get_key_i2c)(struct au0828_rc *ir); | ||
| 44 | }; | ||
| 45 | |||
| 46 | /* | ||
| 47 | * AU8522 has a builtin IR receiver. Add functions to get IR from it | ||
| 48 | */ | ||
| 49 | |||
| 50 | static int au8522_rc_write(struct au0828_rc *ir, u16 reg, u8 data) | ||
| 51 | { | ||
| 52 | int rc; | ||
| 53 | char buf[] = { (reg >> 8) | 0x80, reg & 0xff, data }; | ||
| 54 | struct i2c_msg msg = { .addr = ir->i2c_dev_addr, .flags = 0, | ||
| 55 | .buf = buf, .len = sizeof(buf) }; | ||
| 56 | |||
| 57 | rc = i2c_transfer(ir->dev->i2c_client.adapter, &msg, 1); | ||
| 58 | |||
| 59 | if (rc < 0) | ||
| 60 | return rc; | ||
| 61 | |||
| 62 | return (rc == 1) ? 0 : -EIO; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int au8522_rc_read(struct au0828_rc *ir, u16 reg, int val, | ||
| 66 | char *buf, int size) | ||
| 67 | { | ||
| 68 | int rc; | ||
| 69 | char obuf[3]; | ||
| 70 | struct i2c_msg msg[2] = { { .addr = ir->i2c_dev_addr, .flags = 0, | ||
| 71 | .buf = obuf, .len = 2 }, | ||
| 72 | { .addr = ir->i2c_dev_addr, .flags = I2C_M_RD, | ||
| 73 | .buf = buf, .len = size } }; | ||
| 74 | |||
| 75 | obuf[0] = 0x40 | reg >> 8; | ||
| 76 | obuf[1] = reg & 0xff; | ||
| 77 | if (val >= 0) { | ||
| 78 | obuf[2] = val; | ||
| 79 | msg[0].len++; | ||
| 80 | } | ||
| 81 | |||
| 82 | rc = i2c_transfer(ir->dev->i2c_client.adapter, msg, 2); | ||
| 83 | |||
| 84 | if (rc < 0) | ||
| 85 | return rc; | ||
| 86 | |||
| 87 | return (rc == 2) ? 0 : -EIO; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int au8522_rc_andor(struct au0828_rc *ir, u16 reg, u8 mask, u8 value) | ||
| 91 | { | ||
| 92 | int rc; | ||
| 93 | char buf; | ||
| 94 | |||
| 95 | rc = au8522_rc_read(ir, reg, -1, &buf, 1); | ||
| 96 | if (rc < 0) | ||
| 97 | return rc; | ||
| 98 | |||
| 99 | buf = (buf & ~mask) | (value & mask); | ||
| 100 | |||
| 101 | return au8522_rc_write(ir, reg, buf); | ||
| 102 | } | ||
| 103 | |||
| 104 | #define au8522_rc_set(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), (bit)) | ||
| 105 | #define au8522_rc_clear(ir, reg, bit) au8522_rc_andor(ir, (reg), (bit), 0) | ||
| 106 | |||
| 107 | /* Remote Controller time units */ | ||
| 108 | |||
| 109 | #define AU8522_UNIT 200000 /* ns */ | ||
| 110 | #define NEC_START_SPACE (4500000 / AU8522_UNIT) | ||
| 111 | #define NEC_START_PULSE (562500 * 16) | ||
| 112 | #define RC5_START_SPACE (4 * AU8522_UNIT) | ||
| 113 | #define RC5_START_PULSE 888888 | ||
| 114 | |||
| 115 | static int au0828_get_key_au8522(struct au0828_rc *ir) | ||
| 116 | { | ||
| 117 | unsigned char buf[40]; | ||
| 118 | DEFINE_IR_RAW_EVENT(rawir); | ||
| 119 | int i, j, rc; | ||
| 120 | int prv_bit, bit, width; | ||
| 121 | bool first = true; | ||
| 122 | |||
| 123 | /* Check IR int */ | ||
| 124 | rc = au8522_rc_read(ir, 0xe1, -1, buf, 1); | ||
| 125 | if (rc < 0 || !(buf[0] & (1 << 4))) | ||
| 126 | return 0; | ||
| 127 | |||
| 128 | /* Something arrived. Get the data */ | ||
| 129 | rc = au8522_rc_read(ir, 0xe3, 0x11, buf, sizeof(buf)); | ||
| 130 | |||
| 131 | |||
| 132 | if (rc < 0) | ||
| 133 | return rc; | ||
| 134 | |||
| 135 | /* Disable IR */ | ||
| 136 | au8522_rc_clear(ir, 0xe0, 1 << 4); | ||
| 137 | |||
| 138 | usleep_range(45000, 46000); | ||
| 139 | |||
| 140 | /* Enable IR */ | ||
| 141 | au8522_rc_set(ir, 0xe0, 1 << 4); | ||
| 142 | |||
| 143 | dprintk(16, "RC data received: %*ph\n", 40, buf); | ||
| 144 | |||
| 145 | prv_bit = (buf[0] >> 7) & 0x01; | ||
| 146 | width = 0; | ||
| 147 | for (i = 0; i < sizeof(buf); i++) { | ||
| 148 | for (j = 7; j >= 0; j--) { | ||
| 149 | bit = (buf[i] >> j) & 0x01; | ||
| 150 | if (bit == prv_bit) { | ||
| 151 | width++; | ||
| 152 | continue; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Fix an au8522 bug: the first pulse event | ||
| 157 | * is lost. So, we need to fake it, based on the | ||
| 158 | * protocol. That means that not all raw decoders | ||
| 159 | * will work, as we need to add a hack for each | ||
| 160 | * protocol, based on the first space. | ||
| 161 | * So, we only support RC5 and NEC. | ||
| 162 | */ | ||
| 163 | |||
| 164 | if (first) { | ||
| 165 | first = false; | ||
| 166 | |||
| 167 | init_ir_raw_event(&rawir); | ||
| 168 | rawir.pulse = true; | ||
| 169 | if (width > NEC_START_SPACE - 2 && | ||
| 170 | width < NEC_START_SPACE + 2) { | ||
| 171 | /* NEC protocol */ | ||
| 172 | rawir.duration = NEC_START_PULSE; | ||
| 173 | dprintk(16, "Storing NEC start %s with duration %d", | ||
| 174 | rawir.pulse ? "pulse" : "space", | ||
| 175 | rawir.duration); | ||
| 176 | } else { | ||
| 177 | /* RC5 protocol */ | ||
| 178 | rawir.duration = RC5_START_PULSE; | ||
| 179 | dprintk(16, "Storing RC5 start %s with duration %d", | ||
| 180 | rawir.pulse ? "pulse" : "space", | ||
| 181 | rawir.duration); | ||
| 182 | } | ||
| 183 | ir_raw_event_store(ir->rc, &rawir); | ||
| 184 | } | ||
| 185 | |||
| 186 | init_ir_raw_event(&rawir); | ||
| 187 | rawir.pulse = prv_bit ? false : true; | ||
| 188 | rawir.duration = AU8522_UNIT * width; | ||
| 189 | dprintk(16, "Storing %s with duration %d", | ||
| 190 | rawir.pulse ? "pulse" : "space", | ||
| 191 | rawir.duration); | ||
| 192 | ir_raw_event_store(ir->rc, &rawir); | ||
| 193 | |||
| 194 | width = 1; | ||
| 195 | prv_bit = bit; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | init_ir_raw_event(&rawir); | ||
| 200 | rawir.pulse = prv_bit ? false : true; | ||
| 201 | rawir.duration = AU8522_UNIT * width; | ||
| 202 | dprintk(16, "Storing end %s with duration %d", | ||
| 203 | rawir.pulse ? "pulse" : "space", | ||
| 204 | rawir.duration); | ||
| 205 | ir_raw_event_store(ir->rc, &rawir); | ||
| 206 | |||
| 207 | ir_raw_event_handle(ir->rc); | ||
| 208 | |||
| 209 | return 1; | ||
| 210 | } | ||
| 211 | |||
| 212 | /* | ||
| 213 | * Generic IR code | ||
| 214 | */ | ||
| 215 | |||
| 216 | static void au0828_rc_work(struct work_struct *work) | ||
| 217 | { | ||
| 218 | struct au0828_rc *ir = container_of(work, struct au0828_rc, work.work); | ||
| 219 | int rc; | ||
| 220 | |||
| 221 | rc = ir->get_key_i2c(ir); | ||
| 222 | if (rc < 0) | ||
| 223 | pr_info("Error while getting RC scancode\n"); | ||
| 224 | |||
| 225 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | ||
| 226 | } | ||
| 227 | |||
| 228 | static int au0828_rc_start(struct rc_dev *rc) | ||
| 229 | { | ||
| 230 | struct au0828_rc *ir = rc->priv; | ||
| 231 | |||
| 232 | INIT_DELAYED_WORK(&ir->work, au0828_rc_work); | ||
| 233 | |||
| 234 | /* Enable IR */ | ||
| 235 | au8522_rc_set(ir, 0xe0, 1 << 4); | ||
| 236 | |||
| 237 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static void au0828_rc_stop(struct rc_dev *rc) | ||
| 243 | { | ||
| 244 | struct au0828_rc *ir = rc->priv; | ||
| 245 | |||
| 246 | /* Disable IR */ | ||
| 247 | au8522_rc_clear(ir, 0xe0, 1 << 4); | ||
| 248 | |||
| 249 | cancel_delayed_work_sync(&ir->work); | ||
| 250 | } | ||
| 251 | |||
| 252 | static int au0828_probe_i2c_ir(struct au0828_dev *dev) | ||
| 253 | { | ||
| 254 | int i = 0; | ||
| 255 | const unsigned short addr_list[] = { | ||
| 256 | 0x47, I2C_CLIENT_END | ||
| 257 | }; | ||
| 258 | |||
| 259 | while (addr_list[i] != I2C_CLIENT_END) { | ||
| 260 | if (i2c_probe_func_quick_read(dev->i2c_client.adapter, | ||
| 261 | addr_list[i]) == 1) | ||
| 262 | return addr_list[i]; | ||
| 263 | i++; | ||
| 264 | } | ||
| 265 | |||
| 266 | return -ENODEV; | ||
| 267 | } | ||
| 268 | |||
| 269 | int au0828_rc_register(struct au0828_dev *dev) | ||
| 270 | { | ||
| 271 | struct au0828_rc *ir; | ||
| 272 | struct rc_dev *rc; | ||
| 273 | int err = -ENOMEM; | ||
| 274 | u16 i2c_rc_dev_addr = 0; | ||
| 275 | |||
| 276 | if (!dev->board.has_ir_i2c) | ||
| 277 | return 0; | ||
| 278 | |||
| 279 | i2c_rc_dev_addr = au0828_probe_i2c_ir(dev); | ||
| 280 | if (!i2c_rc_dev_addr) | ||
| 281 | return -ENODEV; | ||
| 282 | |||
| 283 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | ||
| 284 | rc = rc_allocate_device(); | ||
| 285 | if (!ir || !rc) | ||
| 286 | goto error; | ||
| 287 | |||
| 288 | /* record handles to ourself */ | ||
| 289 | ir->dev = dev; | ||
| 290 | dev->ir = ir; | ||
| 291 | ir->rc = rc; | ||
| 292 | |||
| 293 | rc->priv = ir; | ||
| 294 | rc->open = au0828_rc_start; | ||
| 295 | rc->close = au0828_rc_stop; | ||
| 296 | |||
| 297 | if (dev->board.has_ir_i2c) { /* external i2c device */ | ||
| 298 | switch (dev->boardnr) { | ||
| 299 | case AU0828_BOARD_HAUPPAUGE_HVR950Q: | ||
| 300 | rc->map_name = RC_MAP_HAUPPAUGE; | ||
| 301 | ir->get_key_i2c = au0828_get_key_au8522; | ||
| 302 | break; | ||
| 303 | default: | ||
| 304 | err = -ENODEV; | ||
| 305 | goto error; | ||
| 306 | } | ||
| 307 | |||
| 308 | ir->i2c_dev_addr = i2c_rc_dev_addr; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* This is how often we ask the chip for IR information */ | ||
| 312 | ir->polling = 100; /* ms */ | ||
| 313 | |||
| 314 | /* init input device */ | ||
| 315 | snprintf(ir->name, sizeof(ir->name), "au0828 IR (%s)", | ||
| 316 | dev->board.name); | ||
| 317 | |||
| 318 | usb_make_path(dev->usbdev, ir->phys, sizeof(ir->phys)); | ||
| 319 | strlcat(ir->phys, "/input0", sizeof(ir->phys)); | ||
| 320 | |||
| 321 | rc->input_name = ir->name; | ||
| 322 | rc->input_phys = ir->phys; | ||
| 323 | rc->input_id.bustype = BUS_USB; | ||
| 324 | rc->input_id.version = 1; | ||
| 325 | rc->input_id.vendor = le16_to_cpu(dev->usbdev->descriptor.idVendor); | ||
| 326 | rc->input_id.product = le16_to_cpu(dev->usbdev->descriptor.idProduct); | ||
| 327 | rc->dev.parent = &dev->usbdev->dev; | ||
| 328 | rc->driver_name = "au0828-input"; | ||
| 329 | rc->driver_type = RC_DRIVER_IR_RAW; | ||
| 330 | rc->allowed_protocols = RC_BIT_NEC | RC_BIT_RC5; | ||
| 331 | |||
| 332 | /* all done */ | ||
| 333 | err = rc_register_device(rc); | ||
| 334 | if (err) | ||
| 335 | goto error; | ||
| 336 | |||
| 337 | pr_info("Remote controller %s initalized\n", ir->name); | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | |||
| 341 | error: | ||
| 342 | dev->ir = NULL; | ||
| 343 | rc_free_device(rc); | ||
| 344 | kfree(ir); | ||
| 345 | return err; | ||
| 346 | } | ||
| 347 | |||
| 348 | void au0828_rc_unregister(struct au0828_dev *dev) | ||
| 349 | { | ||
| 350 | struct au0828_rc *ir = dev->ir; | ||
| 351 | |||
| 352 | /* skip detach on non attached boards */ | ||
| 353 | if (!ir) | ||
| 354 | return; | ||
| 355 | |||
| 356 | if (ir->rc) | ||
| 357 | rc_unregister_device(ir->rc); | ||
| 358 | |||
| 359 | /* done */ | ||
| 360 | kfree(ir); | ||
| 361 | dev->ir = NULL; | ||
| 362 | } | ||
| 363 | |||
| 364 | int au0828_rc_suspend(struct au0828_dev *dev) | ||
| 365 | { | ||
| 366 | struct au0828_rc *ir = dev->ir; | ||
| 367 | |||
| 368 | if (!ir) | ||
| 369 | return 0; | ||
| 370 | |||
| 371 | cancel_delayed_work_sync(&ir->work); | ||
| 372 | |||
| 373 | return 0; | ||
| 374 | } | ||
| 375 | |||
| 376 | int au0828_rc_resume(struct au0828_dev *dev) | ||
| 377 | { | ||
| 378 | struct au0828_rc *ir = dev->ir; | ||
| 379 | |||
| 380 | if (!ir) | ||
| 381 | return 0; | ||
| 382 | |||
| 383 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | ||
| 384 | |||
| 385 | return 0; | ||
| 386 | } | ||
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 9038194513c5..98f7ea1d6d63 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c | |||
| @@ -787,23 +787,40 @@ static int au0828_i2s_init(struct au0828_dev *dev) | |||
| 787 | 787 | ||
| 788 | /* | 788 | /* |
| 789 | * Auvitek au0828 analog stream enable | 789 | * Auvitek au0828 analog stream enable |
| 790 | * Please set interface0 to AS5 before enable the stream | ||
| 791 | */ | 790 | */ |
| 792 | static int au0828_analog_stream_enable(struct au0828_dev *d) | 791 | static int au0828_analog_stream_enable(struct au0828_dev *d) |
| 793 | { | 792 | { |
| 793 | struct usb_interface *iface; | ||
| 794 | int ret, h, w; | ||
| 795 | |||
| 794 | dprintk(1, "au0828_analog_stream_enable called\n"); | 796 | dprintk(1, "au0828_analog_stream_enable called\n"); |
| 797 | |||
| 798 | iface = usb_ifnum_to_if(d->usbdev, 0); | ||
| 799 | if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) { | ||
| 800 | dprintk(1, "Changing intf#0 to alt 5\n"); | ||
| 801 | /* set au0828 interface0 to AS5 here again */ | ||
| 802 | ret = usb_set_interface(d->usbdev, 0, 5); | ||
| 803 | if (ret < 0) { | ||
| 804 | printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); | ||
| 805 | return -EBUSY; | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 809 | h = d->height / 2 + 2; | ||
| 810 | w = d->width * 2; | ||
| 811 | |||
| 795 | au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); | 812 | au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00); |
| 796 | au0828_writereg(d, 0x106, 0x00); | 813 | au0828_writereg(d, 0x106, 0x00); |
| 797 | /* set x position */ | 814 | /* set x position */ |
| 798 | au0828_writereg(d, 0x110, 0x00); | 815 | au0828_writereg(d, 0x110, 0x00); |
| 799 | au0828_writereg(d, 0x111, 0x00); | 816 | au0828_writereg(d, 0x111, 0x00); |
| 800 | au0828_writereg(d, 0x114, 0xa0); | 817 | au0828_writereg(d, 0x114, w & 0xff); |
| 801 | au0828_writereg(d, 0x115, 0x05); | 818 | au0828_writereg(d, 0x115, w >> 8); |
| 802 | /* set y position */ | 819 | /* set y position */ |
| 803 | au0828_writereg(d, 0x112, 0x00); | 820 | au0828_writereg(d, 0x112, 0x00); |
| 804 | au0828_writereg(d, 0x113, 0x00); | 821 | au0828_writereg(d, 0x113, 0x00); |
| 805 | au0828_writereg(d, 0x116, 0xf2); | 822 | au0828_writereg(d, 0x116, h & 0xff); |
| 806 | au0828_writereg(d, 0x117, 0x00); | 823 | au0828_writereg(d, 0x117, h >> 8); |
| 807 | au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3); | 824 | au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3); |
| 808 | 825 | ||
| 809 | return 0; | 826 | return 0; |
| @@ -1002,15 +1019,6 @@ static int au0828_v4l2_open(struct file *filp) | |||
| 1002 | return -ERESTARTSYS; | 1019 | return -ERESTARTSYS; |
| 1003 | } | 1020 | } |
| 1004 | if (dev->users == 0) { | 1021 | if (dev->users == 0) { |
| 1005 | /* set au0828 interface0 to AS5 here again */ | ||
| 1006 | ret = usb_set_interface(dev->usbdev, 0, 5); | ||
| 1007 | if (ret < 0) { | ||
| 1008 | mutex_unlock(&dev->lock); | ||
| 1009 | printk(KERN_INFO "Au0828 can't set alternate to 5!\n"); | ||
| 1010 | kfree(fh); | ||
| 1011 | return -EBUSY; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | au0828_analog_stream_enable(dev); | 1022 | au0828_analog_stream_enable(dev); |
| 1015 | au0828_analog_stream_reset(dev); | 1023 | au0828_analog_stream_reset(dev); |
| 1016 | 1024 | ||
| @@ -1252,13 +1260,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd, | |||
| 1252 | } | 1260 | } |
| 1253 | } | 1261 | } |
| 1254 | 1262 | ||
| 1255 | /* set au0828 interface0 to AS5 here again */ | ||
| 1256 | ret = usb_set_interface(dev->usbdev, 0, 5); | ||
| 1257 | if (ret < 0) { | ||
| 1258 | printk(KERN_INFO "Au0828 can't set alt setting to 5!\n"); | ||
| 1259 | return -EBUSY; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | au0828_analog_stream_enable(dev); | 1263 | au0828_analog_stream_enable(dev); |
| 1263 | 1264 | ||
| 1264 | return 0; | 1265 | return 0; |
| @@ -1364,9 +1365,11 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) | |||
| 1364 | 1365 | ||
| 1365 | i2c_gate_ctrl(dev, 1); | 1366 | i2c_gate_ctrl(dev, 1); |
| 1366 | 1367 | ||
| 1367 | /* FIXME: when we support something other than NTSC, we are going to | 1368 | /* |
| 1368 | have to make the au0828 bridge adjust the size of its capture | 1369 | * FIXME: when we support something other than 60Hz standards, |
| 1369 | buffer, which is currently hardcoded at 720x480 */ | 1370 | * we are going to have to make the au0828 bridge adjust the size |
| 1371 | * of its capture buffer, which is currently hardcoded at 720x480 | ||
| 1372 | */ | ||
| 1370 | 1373 | ||
| 1371 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, norm); | 1374 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, norm); |
| 1372 | 1375 | ||
| @@ -1723,6 +1726,7 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
| 1723 | dev->vid_timeout_running = 0; | 1726 | dev->vid_timeout_running = 0; |
| 1724 | del_timer_sync(&dev->vid_timeout); | 1727 | del_timer_sync(&dev->vid_timeout); |
| 1725 | 1728 | ||
| 1729 | au0828_analog_stream_disable(dev); | ||
| 1726 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); | 1730 | v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); |
| 1727 | rc = au0828_stream_interrupt(dev); | 1731 | rc = au0828_stream_interrupt(dev); |
| 1728 | if (rc != 0) | 1732 | if (rc != 0) |
| @@ -1915,7 +1919,7 @@ static const struct video_device au0828_video_template = { | |||
| 1915 | .fops = &au0828_v4l_fops, | 1919 | .fops = &au0828_v4l_fops, |
| 1916 | .release = video_device_release, | 1920 | .release = video_device_release, |
| 1917 | .ioctl_ops = &video_ioctl_ops, | 1921 | .ioctl_ops = &video_ioctl_ops, |
| 1918 | .tvnorms = V4L2_STD_NTSC_M, | 1922 | .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL_M, |
| 1919 | }; | 1923 | }; |
| 1920 | 1924 | ||
| 1921 | /**************************************************************************/ | 1925 | /**************************************************************************/ |
| @@ -1928,7 +1932,8 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
| 1928 | struct usb_endpoint_descriptor *endpoint; | 1932 | struct usb_endpoint_descriptor *endpoint; |
| 1929 | int i, ret; | 1933 | int i, ret; |
| 1930 | 1934 | ||
| 1931 | dprintk(1, "au0828_analog_register called!\n"); | 1935 | dprintk(1, "au0828_analog_register called for intf#%d!\n", |
| 1936 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
| 1932 | 1937 | ||
| 1933 | /* set au0828 usb interface0 to as5 */ | 1938 | /* set au0828 usb interface0 to as5 */ |
| 1934 | retval = usb_set_interface(dev->usbdev, | 1939 | retval = usb_set_interface(dev->usbdev, |
| @@ -1952,6 +1957,9 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
| 1952 | dev->max_pkt_size = (tmp & 0x07ff) * | 1957 | dev->max_pkt_size = (tmp & 0x07ff) * |
| 1953 | (((tmp & 0x1800) >> 11) + 1); | 1958 | (((tmp & 0x1800) >> 11) + 1); |
| 1954 | dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; | 1959 | dev->isoc_in_endpointaddr = endpoint->bEndpointAddress; |
| 1960 | dprintk(1, | ||
| 1961 | "Found isoc endpoint 0x%02x, max size = %d\n", | ||
| 1962 | dev->isoc_in_endpointaddr, dev->max_pkt_size); | ||
| 1955 | } | 1963 | } |
| 1956 | } | 1964 | } |
| 1957 | if (!(dev->isoc_in_endpointaddr)) { | 1965 | if (!(dev->isoc_in_endpointaddr)) { |
| @@ -2008,14 +2016,12 @@ int au0828_analog_register(struct au0828_dev *dev, | |||
| 2008 | *dev->vdev = au0828_video_template; | 2016 | *dev->vdev = au0828_video_template; |
| 2009 | dev->vdev->v4l2_dev = &dev->v4l2_dev; | 2017 | dev->vdev->v4l2_dev = &dev->v4l2_dev; |
| 2010 | dev->vdev->lock = &dev->lock; | 2018 | dev->vdev->lock = &dev->lock; |
| 2011 | set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev->flags); | ||
| 2012 | strcpy(dev->vdev->name, "au0828a video"); | 2019 | strcpy(dev->vdev->name, "au0828a video"); |
| 2013 | 2020 | ||
| 2014 | /* Setup the VBI device */ | 2021 | /* Setup the VBI device */ |
| 2015 | *dev->vbi_dev = au0828_video_template; | 2022 | *dev->vbi_dev = au0828_video_template; |
| 2016 | dev->vbi_dev->v4l2_dev = &dev->v4l2_dev; | 2023 | dev->vbi_dev->v4l2_dev = &dev->v4l2_dev; |
| 2017 | dev->vbi_dev->lock = &dev->lock; | 2024 | dev->vbi_dev->lock = &dev->lock; |
| 2018 | set_bit(V4L2_FL_USE_FH_PRIO, &dev->vbi_dev->flags); | ||
| 2019 | strcpy(dev->vbi_dev->name, "au0828a vbi"); | 2025 | strcpy(dev->vbi_dev->name, "au0828a vbi"); |
| 2020 | 2026 | ||
| 2021 | /* Register the v4l2 device */ | 2027 | /* Register the v4l2 device */ |
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h index 7112b9d956fa..96bec05d7dac 100644 --- a/drivers/media/usb/au0828/au0828.h +++ b/drivers/media/usb/au0828/au0828.h | |||
| @@ -88,6 +88,7 @@ struct au0828_board { | |||
| 88 | unsigned int tuner_type; | 88 | unsigned int tuner_type; |
| 89 | unsigned char tuner_addr; | 89 | unsigned char tuner_addr; |
| 90 | unsigned char i2c_clk_divider; | 90 | unsigned char i2c_clk_divider; |
| 91 | unsigned char has_ir_i2c:1; | ||
| 91 | struct au0828_input input[AU0828_MAX_INPUT]; | 92 | struct au0828_input input[AU0828_MAX_INPUT]; |
| 92 | 93 | ||
| 93 | }; | 94 | }; |
| @@ -213,6 +214,10 @@ struct au0828_dev { | |||
| 213 | struct v4l2_device v4l2_dev; | 214 | struct v4l2_device v4l2_dev; |
| 214 | struct v4l2_ctrl_handler v4l2_ctrl_hdl; | 215 | struct v4l2_ctrl_handler v4l2_ctrl_hdl; |
| 215 | #endif | 216 | #endif |
| 217 | #ifdef CONFIG_VIDEO_AU0828_RC | ||
| 218 | struct au0828_rc *ir; | ||
| 219 | #endif | ||
| 220 | |||
| 216 | int users; | 221 | int users; |
| 217 | unsigned int resources; /* resources in use */ | 222 | unsigned int resources; /* resources in use */ |
| 218 | struct video_device *vdev; | 223 | struct video_device *vdev; |
| @@ -319,3 +324,9 @@ extern struct videobuf_queue_ops au0828_vbi_qops; | |||
| 319 | do { if (au0828_debug & level)\ | 324 | do { if (au0828_debug & level)\ |
| 320 | printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ | 325 | printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\ |
| 321 | } while (0) | 326 | } while (0) |
| 327 | |||
| 328 | /* au0828-input.c */ | ||
| 329 | int au0828_rc_register(struct au0828_dev *dev); | ||
| 330 | void au0828_rc_unregister(struct au0828_dev *dev); | ||
| 331 | int au0828_rc_suspend(struct au0828_dev *dev); | ||
| 332 | int au0828_rc_resume(struct au0828_dev *dev); | ||
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index d5d42b6e94be..9caea8344547 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c | |||
| @@ -1169,7 +1169,6 @@ int cpia2_register_camera(struct camera_data *cam) | |||
| 1169 | cam->vdev.lock = &cam->v4l2_lock; | 1169 | cam->vdev.lock = &cam->v4l2_lock; |
| 1170 | cam->vdev.ctrl_handler = hdl; | 1170 | cam->vdev.ctrl_handler = hdl; |
| 1171 | cam->vdev.v4l2_dev = &cam->v4l2_dev; | 1171 | cam->vdev.v4l2_dev = &cam->v4l2_dev; |
| 1172 | set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags); | ||
| 1173 | 1172 | ||
| 1174 | reset_camera_struct_v4l(cam); | 1173 | reset_camera_struct_v4l(cam); |
| 1175 | 1174 | ||
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig index f14c5e89a567..569aa298c03f 100644 --- a/drivers/media/usb/cx231xx/Kconfig +++ b/drivers/media/usb/cx231xx/Kconfig | |||
| @@ -47,6 +47,8 @@ config VIDEO_CX231XX_DVB | |||
| 47 | select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT | 47 | select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT |
| 48 | select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT | 48 | select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT |
| 49 | select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT | 49 | select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT |
| 50 | select DVB_SI2165 if MEDIA_SUBDRV_AUTOSELECT | ||
| 51 | select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT | ||
| 50 | 52 | ||
| 51 | ---help--- | 53 | ---help--- |
| 52 | This adds support for DVB cards based on the | 54 | This adds support for DVB cards based on the |
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 30a0c69fb42f..459bb0e98971 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c | |||
| @@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
| 1563 | f->fmt.pix.width = dev->ts1.width; | 1563 | f->fmt.pix.width = dev->ts1.width; |
| 1564 | f->fmt.pix.height = dev->ts1.height; | 1564 | f->fmt.pix.height = dev->ts1.height; |
| 1565 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | 1565 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; |
| 1566 | f->fmt.pix.priv = 0; | ||
| 1567 | dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n", | 1566 | dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n", |
| 1568 | dev->ts1.width, dev->ts1.height); | 1567 | dev->ts1.width, dev->ts1.height); |
| 1569 | dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); | 1568 | dprintk(3, "exit vidioc_g_fmt_vid_cap()\n"); |
| @@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 1582 | f->fmt.pix.sizeimage = mpeglines * mpeglinesize; | 1581 | f->fmt.pix.sizeimage = mpeglines * mpeglinesize; |
| 1583 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | 1582 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; |
| 1584 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 1583 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 1585 | f->fmt.pix.priv = 0; | ||
| 1586 | dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n", | 1584 | dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n", |
| 1587 | dev->ts1.width, dev->ts1.height); | 1585 | dev->ts1.width, dev->ts1.height); |
| 1588 | dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); | 1586 | dprintk(3, "exit vidioc_try_fmt_vid_cap()\n"); |
| @@ -1923,7 +1921,6 @@ static struct video_device *cx231xx_video_dev_alloc( | |||
| 1923 | vfd->v4l2_dev = &dev->v4l2_dev; | 1921 | vfd->v4l2_dev = &dev->v4l2_dev; |
| 1924 | vfd->lock = &dev->lock; | 1922 | vfd->lock = &dev->lock; |
| 1925 | vfd->release = video_device_release; | 1923 | vfd->release = video_device_release; |
| 1926 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
| 1927 | vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl; | 1924 | vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl; |
| 1928 | video_set_drvdata(vfd, dev); | 1925 | video_set_drvdata(vfd, dev); |
| 1929 | if (dev->tuner_type == TUNER_ABSENT) { | 1926 | if (dev->tuner_type == TUNER_ABSENT) { |
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c index 89de00bf4f82..a428c10e1a16 100644 --- a/drivers/media/usb/cx231xx/cx231xx-avcore.c +++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c | |||
| @@ -352,6 +352,7 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev, | |||
| 352 | case CX231XX_BOARD_CNXT_RDU_253S: | 352 | case CX231XX_BOARD_CNXT_RDU_253S: |
| 353 | case CX231XX_BOARD_CNXT_VIDEO_GRABBER: | 353 | case CX231XX_BOARD_CNXT_VIDEO_GRABBER: |
| 354 | case CX231XX_BOARD_HAUPPAUGE_EXETER: | 354 | case CX231XX_BOARD_HAUPPAUGE_EXETER: |
| 355 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: | ||
| 355 | case CX231XX_BOARD_HAUPPAUGE_USBLIVE2: | 356 | case CX231XX_BOARD_HAUPPAUGE_USBLIVE2: |
| 356 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: | 357 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: |
| 357 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: | 358 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: |
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 2ee03e4ddd86..8039b769f258 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c | |||
| @@ -704,6 +704,84 @@ struct cx231xx_board cx231xx_boards[] = { | |||
| 704 | } | 704 | } |
| 705 | }, | 705 | }, |
| 706 | }, | 706 | }, |
| 707 | [CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx] = { | ||
| 708 | .name = "Hauppauge WinTV 930C-HD (1113xx) / PCTV QuatroStick 521e", | ||
| 709 | .tuner_type = TUNER_NXP_TDA18271, | ||
| 710 | .tuner_addr = 0x60, | ||
| 711 | .tuner_gpio = RDE250_XCV_TUNER, | ||
| 712 | .tuner_sif_gpio = 0x05, | ||
| 713 | .tuner_scl_gpio = 0x1a, | ||
| 714 | .tuner_sda_gpio = 0x1b, | ||
| 715 | .decoder = CX231XX_AVDECODER, | ||
| 716 | .output_mode = OUT_MODE_VIP11, | ||
| 717 | .demod_xfer_mode = 0, | ||
| 718 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
| 719 | .agc_analog_digital_select_gpio = 0x0c, | ||
| 720 | .gpio_pin_status_mask = 0x4001000, | ||
| 721 | .tuner_i2c_master = 1, | ||
| 722 | .demod_i2c_master = 2, | ||
| 723 | .has_dvb = 1, | ||
| 724 | .demod_addr = 0x0e, | ||
| 725 | .norm = V4L2_STD_PAL, | ||
| 726 | |||
| 727 | .input = {{ | ||
| 728 | .type = CX231XX_VMUX_TELEVISION, | ||
| 729 | .vmux = CX231XX_VIN_3_1, | ||
| 730 | .amux = CX231XX_AMUX_VIDEO, | ||
| 731 | .gpio = NULL, | ||
| 732 | }, { | ||
| 733 | .type = CX231XX_VMUX_COMPOSITE1, | ||
| 734 | .vmux = CX231XX_VIN_2_1, | ||
| 735 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 736 | .gpio = NULL, | ||
| 737 | }, { | ||
| 738 | .type = CX231XX_VMUX_SVIDEO, | ||
| 739 | .vmux = CX231XX_VIN_1_1 | | ||
| 740 | (CX231XX_VIN_1_2 << 8) | | ||
| 741 | CX25840_SVIDEO_ON, | ||
| 742 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 743 | .gpio = NULL, | ||
| 744 | } }, | ||
| 745 | }, | ||
| 746 | [CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx] = { | ||
| 747 | .name = "Hauppauge WinTV 930C-HD (1114xx) / PCTV QuatroStick 522e", | ||
| 748 | .tuner_type = TUNER_ABSENT, | ||
| 749 | .tuner_addr = 0x60, | ||
| 750 | .tuner_gpio = RDE250_XCV_TUNER, | ||
| 751 | .tuner_sif_gpio = 0x05, | ||
| 752 | .tuner_scl_gpio = 0x1a, | ||
| 753 | .tuner_sda_gpio = 0x1b, | ||
| 754 | .decoder = CX231XX_AVDECODER, | ||
| 755 | .output_mode = OUT_MODE_VIP11, | ||
| 756 | .demod_xfer_mode = 0, | ||
| 757 | .ctl_pin_status_mask = 0xFFFFFFC4, | ||
| 758 | .agc_analog_digital_select_gpio = 0x0c, | ||
| 759 | .gpio_pin_status_mask = 0x4001000, | ||
| 760 | .tuner_i2c_master = 1, | ||
| 761 | .demod_i2c_master = 2, | ||
| 762 | .has_dvb = 1, | ||
| 763 | .demod_addr = 0x0e, | ||
| 764 | .norm = V4L2_STD_PAL, | ||
| 765 | |||
| 766 | .input = {{ | ||
| 767 | .type = CX231XX_VMUX_TELEVISION, | ||
| 768 | .vmux = CX231XX_VIN_3_1, | ||
| 769 | .amux = CX231XX_AMUX_VIDEO, | ||
| 770 | .gpio = NULL, | ||
| 771 | }, { | ||
| 772 | .type = CX231XX_VMUX_COMPOSITE1, | ||
| 773 | .vmux = CX231XX_VIN_2_1, | ||
| 774 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 775 | .gpio = NULL, | ||
| 776 | }, { | ||
| 777 | .type = CX231XX_VMUX_SVIDEO, | ||
| 778 | .vmux = CX231XX_VIN_1_1 | | ||
| 779 | (CX231XX_VIN_1_2 << 8) | | ||
| 780 | CX25840_SVIDEO_ON, | ||
| 781 | .amux = CX231XX_AMUX_LINE_IN, | ||
| 782 | .gpio = NULL, | ||
| 783 | } }, | ||
| 784 | }, | ||
| 707 | }; | 785 | }; |
| 708 | const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); | 786 | const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); |
| 709 | 787 | ||
| @@ -733,10 +811,20 @@ struct usb_device_id cx231xx_id_table[] = { | |||
| 733 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, | 811 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC}, |
| 734 | {USB_DEVICE(0x2040, 0xb120), | 812 | {USB_DEVICE(0x2040, 0xb120), |
| 735 | .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, | 813 | .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, |
| 814 | {USB_DEVICE(0x2040, 0xb130), | ||
| 815 | .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx}, | ||
| 816 | {USB_DEVICE(0x2040, 0xb131), | ||
| 817 | .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx}, | ||
| 736 | {USB_DEVICE(0x2040, 0xb140), | 818 | {USB_DEVICE(0x2040, 0xb140), |
| 737 | .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, | 819 | .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER}, |
| 738 | {USB_DEVICE(0x2040, 0xc200), | 820 | {USB_DEVICE(0x2040, 0xc200), |
| 739 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2}, | 821 | .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2}, |
| 822 | /* PCTV QuatroStick 521e */ | ||
| 823 | {USB_DEVICE(0x2013, 0x0259), | ||
| 824 | .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx}, | ||
| 825 | /* PCTV QuatroStick 522e */ | ||
| 826 | {USB_DEVICE(0x2013, 0x025e), | ||
| 827 | .driver_info = CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx}, | ||
| 740 | {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001), | 828 | {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001), |
| 741 | .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, | 829 | .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID}, |
| 742 | {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014), | 830 | {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014), |
| @@ -886,6 +974,50 @@ static void cx231xx_config_tuner(struct cx231xx *dev) | |||
| 886 | 974 | ||
| 887 | } | 975 | } |
| 888 | 976 | ||
| 977 | static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len) | ||
| 978 | { | ||
| 979 | int ret = 0; | ||
| 980 | u8 addr = 0xa0 >> 1; | ||
| 981 | u8 start_offset = 0; | ||
| 982 | int len_todo = len; | ||
| 983 | u8 *eedata_cur = eedata; | ||
| 984 | int i; | ||
| 985 | struct i2c_msg msg_write = { .addr = addr, .flags = 0, | ||
| 986 | .buf = &start_offset, .len = 1 }; | ||
| 987 | struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD }; | ||
| 988 | |||
| 989 | /* mutex_lock(&dev->i2c_lock); */ | ||
| 990 | cx231xx_enable_i2c_port_3(dev, false); | ||
| 991 | |||
| 992 | /* start reading at offset 0 */ | ||
| 993 | ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1); | ||
| 994 | if (ret < 0) { | ||
| 995 | cx231xx_err("Can't read eeprom\n"); | ||
| 996 | return ret; | ||
| 997 | } | ||
| 998 | |||
| 999 | while (len_todo > 0) { | ||
| 1000 | msg_read.len = (len_todo > 64) ? 64 : len_todo; | ||
| 1001 | msg_read.buf = eedata_cur; | ||
| 1002 | |||
| 1003 | ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1); | ||
| 1004 | if (ret < 0) { | ||
| 1005 | cx231xx_err("Can't read eeprom\n"); | ||
| 1006 | return ret; | ||
| 1007 | } | ||
| 1008 | eedata_cur += msg_read.len; | ||
| 1009 | len_todo -= msg_read.len; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | cx231xx_enable_i2c_port_3(dev, true); | ||
| 1013 | /* mutex_unlock(&dev->i2c_lock); */ | ||
| 1014 | |||
| 1015 | for (i = 0; i + 15 < len; i += 16) | ||
| 1016 | cx231xx_info("i2c eeprom %02x: %*ph\n", i, 16, &eedata[i]); | ||
| 1017 | |||
| 1018 | return 0; | ||
| 1019 | } | ||
| 1020 | |||
| 889 | void cx231xx_card_setup(struct cx231xx *dev) | 1021 | void cx231xx_card_setup(struct cx231xx *dev) |
| 890 | { | 1022 | { |
| 891 | 1023 | ||
| @@ -917,6 +1049,21 @@ void cx231xx_card_setup(struct cx231xx *dev) | |||
| 917 | else | 1049 | else |
| 918 | cx231xx_config_tuner(dev); | 1050 | cx231xx_config_tuner(dev); |
| 919 | } | 1051 | } |
| 1052 | |||
| 1053 | switch (dev->model) { | ||
| 1054 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: | ||
| 1055 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: | ||
| 1056 | { | ||
| 1057 | struct tveeprom tvee; | ||
| 1058 | static u8 eeprom[256]; | ||
| 1059 | |||
| 1060 | read_eeprom(dev, eeprom, sizeof(eeprom)); | ||
| 1061 | tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client, | ||
| 1062 | &tvee, eeprom + 0xc0); | ||
| 1063 | break; | ||
| 1064 | } | ||
| 1065 | } | ||
| 1066 | |||
| 920 | } | 1067 | } |
| 921 | 1068 | ||
| 922 | /* | 1069 | /* |
| @@ -964,12 +1111,6 @@ void cx231xx_release_resources(struct cx231xx *dev) | |||
| 964 | 1111 | ||
| 965 | /* Mark device as unused */ | 1112 | /* Mark device as unused */ |
| 966 | clear_bit(dev->devno, &cx231xx_devused); | 1113 | clear_bit(dev->devno, &cx231xx_devused); |
| 967 | |||
| 968 | kfree(dev->video_mode.alt_max_pkt_size); | ||
| 969 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
| 970 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
| 971 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
| 972 | kfree(dev); | ||
| 973 | } | 1114 | } |
| 974 | 1115 | ||
| 975 | /* | 1116 | /* |
| @@ -1003,7 +1144,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
| 1003 | dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; | 1144 | dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write; |
| 1004 | 1145 | ||
| 1005 | /* Query cx231xx to find what pcb config it is related to */ | 1146 | /* Query cx231xx to find what pcb config it is related to */ |
| 1006 | initialize_cx231xx(dev); | 1147 | retval = initialize_cx231xx(dev); |
| 1148 | if (retval < 0) { | ||
| 1149 | cx231xx_errdev("Failed to read PCB config\n"); | ||
| 1150 | return retval; | ||
| 1151 | } | ||
| 1007 | 1152 | ||
| 1008 | /*To workaround error number=-71 on EP0 for VideoGrabber, | 1153 | /*To workaround error number=-71 on EP0 for VideoGrabber, |
| 1009 | need set alt here.*/ | 1154 | need set alt here.*/ |
| @@ -1121,6 +1266,117 @@ static void flush_request_modules(struct cx231xx *dev) | |||
| 1121 | #define flush_request_modules(dev) | 1266 | #define flush_request_modules(dev) |
| 1122 | #endif /* CONFIG_MODULES */ | 1267 | #endif /* CONFIG_MODULES */ |
| 1123 | 1268 | ||
| 1269 | static int cx231xx_init_v4l2(struct cx231xx *dev, | ||
| 1270 | struct usb_device *udev, | ||
| 1271 | struct usb_interface *interface, | ||
| 1272 | int isoc_pipe) | ||
| 1273 | { | ||
| 1274 | struct usb_interface *uif; | ||
| 1275 | int i, idx; | ||
| 1276 | |||
| 1277 | /* Video Init */ | ||
| 1278 | |||
| 1279 | /* compute alternate max packet sizes for video */ | ||
| 1280 | idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1; | ||
| 1281 | if (idx >= dev->max_iad_interface_count) { | ||
| 1282 | cx231xx_errdev("Video PCB interface #%d doesn't exist\n", idx); | ||
| 1283 | return -ENODEV; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | uif = udev->actconfig->interface[idx]; | ||
| 1287 | |||
| 1288 | dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress; | ||
| 1289 | dev->video_mode.num_alt = uif->num_altsetting; | ||
| 1290 | |||
| 1291 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
| 1292 | dev->video_mode.end_point_addr, | ||
| 1293 | dev->video_mode.num_alt); | ||
| 1294 | |||
| 1295 | dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL); | ||
| 1296 | if (dev->video_mode.alt_max_pkt_size == NULL) { | ||
| 1297 | cx231xx_errdev("out of memory!\n"); | ||
| 1298 | return -ENOMEM; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | for (i = 0; i < dev->video_mode.num_alt; i++) { | ||
| 1302 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); | ||
| 1303 | dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
| 1304 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
| 1305 | dev->video_mode.alt_max_pkt_size[i]); | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | /* VBI Init */ | ||
| 1309 | |||
| 1310 | idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1; | ||
| 1311 | if (idx >= dev->max_iad_interface_count) { | ||
| 1312 | cx231xx_errdev("VBI PCB interface #%d doesn't exist\n", idx); | ||
| 1313 | return -ENODEV; | ||
| 1314 | } | ||
| 1315 | uif = udev->actconfig->interface[idx]; | ||
| 1316 | |||
| 1317 | dev->vbi_mode.end_point_addr = | ||
| 1318 | uif->altsetting[0].endpoint[isoc_pipe].desc. | ||
| 1319 | bEndpointAddress; | ||
| 1320 | |||
| 1321 | dev->vbi_mode.num_alt = uif->num_altsetting; | ||
| 1322 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
| 1323 | dev->vbi_mode.end_point_addr, | ||
| 1324 | dev->vbi_mode.num_alt); | ||
| 1325 | |||
| 1326 | /* compute alternate max packet sizes for vbi */ | ||
| 1327 | dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL); | ||
| 1328 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | ||
| 1329 | cx231xx_errdev("out of memory!\n"); | ||
| 1330 | return -ENOMEM; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | for (i = 0; i < dev->vbi_mode.num_alt; i++) { | ||
| 1334 | u16 tmp = | ||
| 1335 | le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
| 1336 | desc.wMaxPacketSize); | ||
| 1337 | dev->vbi_mode.alt_max_pkt_size[i] = | ||
| 1338 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
| 1339 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
| 1340 | dev->vbi_mode.alt_max_pkt_size[i]); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | /* Sliced CC VBI init */ | ||
| 1344 | |||
| 1345 | /* compute alternate max packet sizes for sliced CC */ | ||
| 1346 | idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1; | ||
| 1347 | if (idx >= dev->max_iad_interface_count) { | ||
| 1348 | cx231xx_errdev("Sliced CC PCB interface #%d doesn't exist\n", idx); | ||
| 1349 | return -ENODEV; | ||
| 1350 | } | ||
| 1351 | uif = udev->actconfig->interface[idx]; | ||
| 1352 | |||
| 1353 | dev->sliced_cc_mode.end_point_addr = | ||
| 1354 | uif->altsetting[0].endpoint[isoc_pipe].desc. | ||
| 1355 | bEndpointAddress; | ||
| 1356 | |||
| 1357 | dev->sliced_cc_mode.num_alt = uif->num_altsetting; | ||
| 1358 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
| 1359 | dev->sliced_cc_mode.end_point_addr, | ||
| 1360 | dev->sliced_cc_mode.num_alt); | ||
| 1361 | dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL); | ||
| 1362 | |||
| 1363 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | ||
| 1364 | cx231xx_errdev("out of memory!\n"); | ||
| 1365 | return -ENOMEM; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { | ||
| 1369 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
| 1370 | desc.wMaxPacketSize); | ||
| 1371 | dev->sliced_cc_mode.alt_max_pkt_size[i] = | ||
| 1372 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
| 1373 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
| 1374 | dev->sliced_cc_mode.alt_max_pkt_size[i]); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | return 0; | ||
| 1378 | } | ||
| 1379 | |||
| 1124 | /* | 1380 | /* |
| 1125 | * cx231xx_usb_probe() | 1381 | * cx231xx_usb_probe() |
| 1126 | * checks for supported devices | 1382 | * checks for supported devices |
| @@ -1135,6 +1391,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
| 1135 | int nr = 0, ifnum; | 1391 | int nr = 0, ifnum; |
| 1136 | int i, isoc_pipe = 0; | 1392 | int i, isoc_pipe = 0; |
| 1137 | char *speed; | 1393 | char *speed; |
| 1394 | u8 idx; | ||
| 1138 | struct usb_interface_assoc_descriptor *assoc_desc; | 1395 | struct usb_interface_assoc_descriptor *assoc_desc; |
| 1139 | 1396 | ||
| 1140 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 1397 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
| @@ -1157,16 +1414,16 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
| 1157 | } | 1414 | } |
| 1158 | } while (test_and_set_bit(nr, &cx231xx_devused)); | 1415 | } while (test_and_set_bit(nr, &cx231xx_devused)); |
| 1159 | 1416 | ||
| 1417 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
| 1418 | |||
| 1160 | /* allocate memory for our device state and initialize it */ | 1419 | /* allocate memory for our device state and initialize it */ |
| 1161 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1420 | dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL); |
| 1162 | if (dev == NULL) { | 1421 | if (dev == NULL) { |
| 1163 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); | 1422 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); |
| 1164 | clear_bit(nr, &cx231xx_devused); | 1423 | clear_bit(nr, &cx231xx_devused); |
| 1165 | return -ENOMEM; | 1424 | return -ENOMEM; |
| 1166 | } | 1425 | } |
| 1167 | 1426 | ||
| 1168 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
| 1169 | |||
| 1170 | snprintf(dev->name, 29, "cx231xx #%d", nr); | 1427 | snprintf(dev->name, 29, "cx231xx #%d", nr); |
| 1171 | dev->devno = nr; | 1428 | dev->devno = nr; |
| 1172 | dev->model = id->driver_info; | 1429 | dev->model = id->driver_info; |
| @@ -1185,8 +1442,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
| 1185 | dev->vbi_or_sliced_cc_mode = 0; | 1442 | dev->vbi_or_sliced_cc_mode = 0; |
| 1186 | 1443 | ||
| 1187 | /* get maximum no.of IAD interfaces */ | 1444 | /* get maximum no.of IAD interfaces */ |
| 1188 | assoc_desc = udev->actconfig->intf_assoc[0]; | 1445 | dev->max_iad_interface_count = udev->config->desc.bNumInterfaces; |
| 1189 | dev->max_iad_interface_count = assoc_desc->bInterfaceCount; | ||
| 1190 | 1446 | ||
| 1191 | /* init CIR module TBD */ | 1447 | /* init CIR module TBD */ |
| 1192 | 1448 | ||
| @@ -1238,120 +1494,31 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
| 1238 | /* save our data pointer in this interface device */ | 1494 | /* save our data pointer in this interface device */ |
| 1239 | usb_set_intfdata(interface, dev); | 1495 | usb_set_intfdata(interface, dev); |
| 1240 | 1496 | ||
| 1241 | /* | ||
| 1242 | * AV device initialization - only done at the last interface | ||
| 1243 | */ | ||
| 1244 | |||
| 1245 | /* Create v4l2 device */ | 1497 | /* Create v4l2 device */ |
| 1246 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | 1498 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
| 1247 | if (retval) { | 1499 | if (retval) { |
| 1248 | cx231xx_errdev("v4l2_device_register failed\n"); | 1500 | cx231xx_errdev("v4l2_device_register failed\n"); |
| 1249 | retval = -EIO; | ||
| 1250 | goto err_v4l2; | 1501 | goto err_v4l2; |
| 1251 | } | 1502 | } |
| 1503 | |||
| 1252 | /* allocate device struct */ | 1504 | /* allocate device struct */ |
| 1253 | retval = cx231xx_init_dev(dev, udev, nr); | 1505 | retval = cx231xx_init_dev(dev, udev, nr); |
| 1254 | if (retval) | 1506 | if (retval) |
| 1255 | goto err_init; | 1507 | goto err_init; |
| 1256 | 1508 | ||
| 1257 | /* compute alternate max packet sizes for video */ | 1509 | retval = cx231xx_init_v4l2(dev, udev, interface, isoc_pipe); |
| 1258 | uif = udev->actconfig->interface[dev->current_pcb_config. | 1510 | if (retval) |
| 1259 | hs_config_info[0].interface_info.video_index + 1]; | 1511 | goto err_init; |
| 1260 | |||
| 1261 | dev->video_mode.end_point_addr = uif->altsetting[0]. | ||
| 1262 | endpoint[isoc_pipe].desc.bEndpointAddress; | ||
| 1263 | |||
| 1264 | dev->video_mode.num_alt = uif->num_altsetting; | ||
| 1265 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
| 1266 | dev->video_mode.end_point_addr, | ||
| 1267 | dev->video_mode.num_alt); | ||
| 1268 | dev->video_mode.alt_max_pkt_size = | ||
| 1269 | kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL); | ||
| 1270 | |||
| 1271 | if (dev->video_mode.alt_max_pkt_size == NULL) { | ||
| 1272 | cx231xx_errdev("out of memory!\n"); | ||
| 1273 | retval = -ENOMEM; | ||
| 1274 | goto err_video_alt; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | for (i = 0; i < dev->video_mode.num_alt; i++) { | ||
| 1278 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
| 1279 | desc.wMaxPacketSize); | ||
| 1280 | dev->video_mode.alt_max_pkt_size[i] = | ||
| 1281 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
| 1282 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
| 1283 | dev->video_mode.alt_max_pkt_size[i]); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* compute alternate max packet sizes for vbi */ | ||
| 1287 | uif = udev->actconfig->interface[dev->current_pcb_config. | ||
| 1288 | hs_config_info[0].interface_info. | ||
| 1289 | vanc_index + 1]; | ||
| 1290 | |||
| 1291 | dev->vbi_mode.end_point_addr = | ||
| 1292 | uif->altsetting[0].endpoint[isoc_pipe].desc. | ||
| 1293 | bEndpointAddress; | ||
| 1294 | |||
| 1295 | dev->vbi_mode.num_alt = uif->num_altsetting; | ||
| 1296 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
| 1297 | dev->vbi_mode.end_point_addr, | ||
| 1298 | dev->vbi_mode.num_alt); | ||
| 1299 | dev->vbi_mode.alt_max_pkt_size = | ||
| 1300 | kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL); | ||
| 1301 | |||
| 1302 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | ||
| 1303 | cx231xx_errdev("out of memory!\n"); | ||
| 1304 | retval = -ENOMEM; | ||
| 1305 | goto err_vbi_alt; | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | for (i = 0; i < dev->vbi_mode.num_alt; i++) { | ||
| 1309 | u16 tmp = | ||
| 1310 | le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
| 1311 | desc.wMaxPacketSize); | ||
| 1312 | dev->vbi_mode.alt_max_pkt_size[i] = | ||
| 1313 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
| 1314 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
| 1315 | dev->vbi_mode.alt_max_pkt_size[i]); | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | /* compute alternate max packet sizes for sliced CC */ | ||
| 1319 | uif = udev->actconfig->interface[dev->current_pcb_config. | ||
| 1320 | hs_config_info[0].interface_info. | ||
| 1321 | hanc_index + 1]; | ||
| 1322 | |||
| 1323 | dev->sliced_cc_mode.end_point_addr = | ||
| 1324 | uif->altsetting[0].endpoint[isoc_pipe].desc. | ||
| 1325 | bEndpointAddress; | ||
| 1326 | |||
| 1327 | dev->sliced_cc_mode.num_alt = uif->num_altsetting; | ||
| 1328 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | ||
| 1329 | dev->sliced_cc_mode.end_point_addr, | ||
| 1330 | dev->sliced_cc_mode.num_alt); | ||
| 1331 | dev->sliced_cc_mode.alt_max_pkt_size = | ||
| 1332 | kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL); | ||
| 1333 | |||
| 1334 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | ||
| 1335 | cx231xx_errdev("out of memory!\n"); | ||
| 1336 | retval = -ENOMEM; | ||
| 1337 | goto err_sliced_cc_alt; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { | ||
| 1341 | u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. | ||
| 1342 | desc.wMaxPacketSize); | ||
| 1343 | dev->sliced_cc_mode.alt_max_pkt_size[i] = | ||
| 1344 | (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); | ||
| 1345 | cx231xx_info("Alternate setting %i, max size= %i\n", i, | ||
| 1346 | dev->sliced_cc_mode.alt_max_pkt_size[i]); | ||
| 1347 | } | ||
| 1348 | 1512 | ||
| 1349 | if (dev->current_pcb_config.ts1_source != 0xff) { | 1513 | if (dev->current_pcb_config.ts1_source != 0xff) { |
| 1350 | /* compute alternate max packet sizes for TS1 */ | 1514 | /* compute alternate max packet sizes for TS1 */ |
| 1351 | uif = udev->actconfig->interface[dev->current_pcb_config. | 1515 | idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1; |
| 1352 | hs_config_info[0]. | 1516 | if (idx >= dev->max_iad_interface_count) { |
| 1353 | interface_info. | 1517 | cx231xx_errdev("TS1 PCB interface #%d doesn't exist\n", idx); |
| 1354 | ts1_index + 1]; | 1518 | retval = -ENODEV; |
| 1519 | goto err_video_alt; | ||
| 1520 | } | ||
| 1521 | uif = udev->actconfig->interface[idx]; | ||
| 1355 | 1522 | ||
| 1356 | dev->ts1_mode.end_point_addr = | 1523 | dev->ts1_mode.end_point_addr = |
| 1357 | uif->altsetting[0].endpoint[isoc_pipe]. | 1524 | uif->altsetting[0].endpoint[isoc_pipe]. |
| @@ -1361,13 +1528,12 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
| 1361 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", | 1528 | cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n", |
| 1362 | dev->ts1_mode.end_point_addr, | 1529 | dev->ts1_mode.end_point_addr, |
| 1363 | dev->ts1_mode.num_alt); | 1530 | dev->ts1_mode.num_alt); |
| 1364 | dev->ts1_mode.alt_max_pkt_size = | ||
| 1365 | kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL); | ||
| 1366 | 1531 | ||
| 1532 | dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL); | ||
| 1367 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { | 1533 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { |
| 1368 | cx231xx_errdev("out of memory!\n"); | 1534 | cx231xx_errdev("out of memory!\n"); |
| 1369 | retval = -ENOMEM; | 1535 | retval = -ENOMEM; |
| 1370 | goto err_ts1_alt; | 1536 | goto err_video_alt; |
| 1371 | } | 1537 | } |
| 1372 | 1538 | ||
| 1373 | for (i = 0; i < dev->ts1_mode.num_alt; i++) { | 1539 | for (i = 0; i < dev->ts1_mode.num_alt; i++) { |
| @@ -1394,12 +1560,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
| 1394 | request_modules(dev); | 1560 | request_modules(dev); |
| 1395 | 1561 | ||
| 1396 | return 0; | 1562 | return 0; |
| 1397 | err_ts1_alt: | ||
| 1398 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
| 1399 | err_sliced_cc_alt: | ||
| 1400 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
| 1401 | err_vbi_alt: | ||
| 1402 | kfree(dev->video_mode.alt_max_pkt_size); | ||
| 1403 | err_video_alt: | 1563 | err_video_alt: |
| 1404 | /* cx231xx_uninit_dev: */ | 1564 | /* cx231xx_uninit_dev: */ |
| 1405 | cx231xx_close_extension(dev); | 1565 | cx231xx_close_extension(dev); |
| @@ -1415,7 +1575,6 @@ err_v4l2: | |||
| 1415 | err_if: | 1575 | err_if: |
| 1416 | usb_put_dev(udev); | 1576 | usb_put_dev(udev); |
| 1417 | clear_bit(dev->devno, &cx231xx_devused); | 1577 | clear_bit(dev->devno, &cx231xx_devused); |
| 1418 | kfree(dev); | ||
| 1419 | return retval; | 1578 | return retval; |
| 1420 | } | 1579 | } |
| 1421 | 1580 | ||
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c index 4ba3ce09b713..513194aa6561 100644 --- a/drivers/media/usb/cx231xx/cx231xx-core.c +++ b/drivers/media/usb/cx231xx/cx231xx-core.c | |||
| @@ -726,6 +726,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) | |||
| 726 | errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); | 726 | errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); |
| 727 | break; | 727 | break; |
| 728 | case CX231XX_BOARD_HAUPPAUGE_EXETER: | 728 | case CX231XX_BOARD_HAUPPAUGE_EXETER: |
| 729 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: | ||
| 729 | errCode = cx231xx_set_power_mode(dev, | 730 | errCode = cx231xx_set_power_mode(dev, |
| 730 | POLARIS_AVMODE_DIGITAL); | 731 | POLARIS_AVMODE_DIGITAL); |
| 731 | break; | 732 | break; |
| @@ -744,6 +745,7 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) | |||
| 744 | case CX231XX_BOARD_CNXT_RDE_253S: | 745 | case CX231XX_BOARD_CNXT_RDE_253S: |
| 745 | case CX231XX_BOARD_CNXT_RDU_253S: | 746 | case CX231XX_BOARD_CNXT_RDU_253S: |
| 746 | case CX231XX_BOARD_HAUPPAUGE_EXETER: | 747 | case CX231XX_BOARD_HAUPPAUGE_EXETER: |
| 748 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: | ||
| 747 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: | 749 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: |
| 748 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: | 750 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: |
| 749 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: | 751 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: |
| @@ -1379,6 +1381,7 @@ int cx231xx_dev_init(struct cx231xx *dev) | |||
| 1379 | case CX231XX_BOARD_CNXT_RDE_253S: | 1381 | case CX231XX_BOARD_CNXT_RDE_253S: |
| 1380 | case CX231XX_BOARD_CNXT_RDU_253S: | 1382 | case CX231XX_BOARD_CNXT_RDU_253S: |
| 1381 | case CX231XX_BOARD_HAUPPAUGE_EXETER: | 1383 | case CX231XX_BOARD_HAUPPAUGE_EXETER: |
| 1384 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: | ||
| 1382 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: | 1385 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: |
| 1383 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: | 1386 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: |
| 1384 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: | 1387 | case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC: |
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 4504bc6a700b..1fa79741d199 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c | |||
| @@ -32,7 +32,9 @@ | |||
| 32 | #include "tda18271.h" | 32 | #include "tda18271.h" |
| 33 | #include "s5h1411.h" | 33 | #include "s5h1411.h" |
| 34 | #include "lgdt3305.h" | 34 | #include "lgdt3305.h" |
| 35 | #include "si2165.h" | ||
| 35 | #include "mb86a20s.h" | 36 | #include "mb86a20s.h" |
| 37 | #include "si2157.h" | ||
| 36 | 38 | ||
| 37 | MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); | 39 | MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); |
| 38 | MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); | 40 | MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); |
| @@ -67,6 +69,7 @@ struct cx231xx_dvb { | |||
| 67 | struct dmx_frontend fe_hw; | 69 | struct dmx_frontend fe_hw; |
| 68 | struct dmx_frontend fe_mem; | 70 | struct dmx_frontend fe_mem; |
| 69 | struct dvb_net net; | 71 | struct dvb_net net; |
| 72 | struct i2c_client *i2c_client_tuner; | ||
| 70 | }; | 73 | }; |
| 71 | 74 | ||
| 72 | static struct s5h1432_config dvico_s5h1432_config = { | 75 | static struct s5h1432_config dvico_s5h1432_config = { |
| @@ -151,6 +154,18 @@ static struct tda18271_config pv_tda18271_config = { | |||
| 151 | .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, | 154 | .small_i2c = TDA18271_03_BYTE_CHUNK_INIT, |
| 152 | }; | 155 | }; |
| 153 | 156 | ||
| 157 | static const struct si2165_config hauppauge_930C_HD_1113xx_si2165_config = { | ||
| 158 | .i2c_addr = 0x64, | ||
| 159 | .chip_mode = SI2165_MODE_PLL_XTAL, | ||
| 160 | .ref_freq_Hz = 16000000, | ||
| 161 | }; | ||
| 162 | |||
| 163 | static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = { | ||
| 164 | .i2c_addr = 0x64, | ||
| 165 | .chip_mode = SI2165_MODE_PLL_EXT, | ||
| 166 | .ref_freq_Hz = 24000000, | ||
| 167 | }; | ||
| 168 | |||
| 154 | static inline void print_err_status(struct cx231xx *dev, int packet, int status) | 169 | static inline void print_err_status(struct cx231xx *dev, int packet, int status) |
| 155 | { | 170 | { |
| 156 | char *errmsg = "Unknown"; | 171 | char *errmsg = "Unknown"; |
| @@ -549,11 +564,18 @@ fail_adapter: | |||
| 549 | 564 | ||
| 550 | static void unregister_dvb(struct cx231xx_dvb *dvb) | 565 | static void unregister_dvb(struct cx231xx_dvb *dvb) |
| 551 | { | 566 | { |
| 567 | struct i2c_client *client; | ||
| 552 | dvb_net_release(&dvb->net); | 568 | dvb_net_release(&dvb->net); |
| 553 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); | 569 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); |
| 554 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); | 570 | dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); |
| 555 | dvb_dmxdev_release(&dvb->dmxdev); | 571 | dvb_dmxdev_release(&dvb->dmxdev); |
| 556 | dvb_dmx_release(&dvb->demux); | 572 | dvb_dmx_release(&dvb->demux); |
| 573 | client = dvb->i2c_client_tuner; | ||
| 574 | /* remove I2C tuner */ | ||
| 575 | if (client) { | ||
| 576 | module_put(client->dev.driver->owner); | ||
| 577 | i2c_unregister_device(client); | ||
| 578 | } | ||
| 557 | dvb_unregister_frontend(dvb->frontend); | 579 | dvb_unregister_frontend(dvb->frontend); |
| 558 | dvb_frontend_detach(dvb->frontend); | 580 | dvb_frontend_detach(dvb->frontend); |
| 559 | dvb_unregister_adapter(&dvb->adapter); | 581 | dvb_unregister_adapter(&dvb->adapter); |
| @@ -704,6 +726,89 @@ static int dvb_init(struct cx231xx *dev) | |||
| 704 | &hcw_tda18271_config); | 726 | &hcw_tda18271_config); |
| 705 | break; | 727 | break; |
| 706 | 728 | ||
| 729 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: | ||
| 730 | |||
| 731 | dev->dvb->frontend = dvb_attach(si2165_attach, | ||
| 732 | &hauppauge_930C_HD_1113xx_si2165_config, | ||
| 733 | &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap | ||
| 734 | ); | ||
| 735 | |||
| 736 | if (dev->dvb->frontend == NULL) { | ||
| 737 | printk(DRIVER_NAME | ||
| 738 | ": Failed to attach SI2165 front end\n"); | ||
| 739 | result = -EINVAL; | ||
| 740 | goto out_free; | ||
| 741 | } | ||
| 742 | |||
| 743 | dev->dvb->frontend->ops.i2c_gate_ctrl = 0; | ||
| 744 | |||
| 745 | /* define general-purpose callback pointer */ | ||
| 746 | dvb->frontend->callback = cx231xx_tuner_callback; | ||
| 747 | |||
| 748 | dvb_attach(tda18271_attach, dev->dvb->frontend, | ||
| 749 | 0x60, | ||
| 750 | &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, | ||
| 751 | &hcw_tda18271_config); | ||
| 752 | |||
| 753 | dev->cx231xx_reset_analog_tuner = NULL; | ||
| 754 | break; | ||
| 755 | |||
| 756 | case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: | ||
| 757 | { | ||
| 758 | struct i2c_client *client; | ||
| 759 | struct i2c_board_info info; | ||
| 760 | struct si2157_config si2157_config; | ||
| 761 | |||
| 762 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
| 763 | |||
| 764 | dev->dvb->frontend = dvb_attach(si2165_attach, | ||
| 765 | &pctv_quatro_stick_1114xx_si2165_config, | ||
| 766 | &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap | ||
| 767 | ); | ||
| 768 | |||
| 769 | if (dev->dvb->frontend == NULL) { | ||
| 770 | printk(DRIVER_NAME | ||
| 771 | ": Failed to attach SI2165 front end\n"); | ||
| 772 | result = -EINVAL; | ||
| 773 | goto out_free; | ||
| 774 | } | ||
| 775 | |||
| 776 | dev->dvb->frontend->ops.i2c_gate_ctrl = 0; | ||
| 777 | |||
| 778 | /* define general-purpose callback pointer */ | ||
| 779 | dvb->frontend->callback = cx231xx_tuner_callback; | ||
| 780 | |||
| 781 | /* attach tuner */ | ||
| 782 | memset(&si2157_config, 0, sizeof(si2157_config)); | ||
| 783 | si2157_config.fe = dev->dvb->frontend; | ||
| 784 | si2157_config.inversion = true; | ||
| 785 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); | ||
| 786 | info.addr = 0x60; | ||
| 787 | info.platform_data = &si2157_config; | ||
| 788 | request_module("si2157"); | ||
| 789 | |||
| 790 | client = i2c_new_device( | ||
| 791 | &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, | ||
| 792 | &info); | ||
| 793 | if (client == NULL || client->dev.driver == NULL) { | ||
| 794 | dvb_frontend_detach(dev->dvb->frontend); | ||
| 795 | result = -ENODEV; | ||
| 796 | goto out_free; | ||
| 797 | } | ||
| 798 | |||
| 799 | if (!try_module_get(client->dev.driver->owner)) { | ||
| 800 | i2c_unregister_device(client); | ||
| 801 | dvb_frontend_detach(dev->dvb->frontend); | ||
| 802 | result = -ENODEV; | ||
| 803 | goto out_free; | ||
| 804 | } | ||
| 805 | |||
| 806 | dev->cx231xx_reset_analog_tuner = NULL; | ||
| 807 | |||
| 808 | dev->dvb->i2c_client_tuner = client; | ||
| 809 | break; | ||
| 810 | } | ||
| 811 | |||
| 707 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: | 812 | case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: |
| 708 | case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: | 813 | case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID: |
| 709 | 814 | ||
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c index 46d52fac8680..05f0434919d4 100644 --- a/drivers/media/usb/cx231xx/cx231xx-input.c +++ b/drivers/media/usb/cx231xx/cx231xx-input.c | |||
| @@ -21,11 +21,12 @@ | |||
| 21 | #include "cx231xx.h" | 21 | #include "cx231xx.h" |
| 22 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/bitrev.h> | ||
| 24 | 25 | ||
| 25 | #define MODULE_NAME "cx231xx-input" | 26 | #define MODULE_NAME "cx231xx-input" |
| 26 | 27 | ||
| 27 | static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, | 28 | static int get_key_isdbt(struct IR_i2c *ir, enum rc_type *protocol, |
| 28 | u32 *ir_raw) | 29 | u32 *pscancode, u8 *toggle) |
| 29 | { | 30 | { |
| 30 | int rc; | 31 | int rc; |
| 31 | u8 cmd, scancode; | 32 | u8 cmd, scancode; |
| @@ -46,21 +47,14 @@ static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, | |||
| 46 | if (cmd == 0xff) | 47 | if (cmd == 0xff) |
| 47 | return 0; | 48 | return 0; |
| 48 | 49 | ||
| 49 | scancode = | 50 | scancode = bitrev8(cmd); |
| 50 | ((cmd & 0x01) ? 0x80 : 0) | | ||
| 51 | ((cmd & 0x02) ? 0x40 : 0) | | ||
| 52 | ((cmd & 0x04) ? 0x20 : 0) | | ||
| 53 | ((cmd & 0x08) ? 0x10 : 0) | | ||
| 54 | ((cmd & 0x10) ? 0x08 : 0) | | ||
| 55 | ((cmd & 0x20) ? 0x04 : 0) | | ||
| 56 | ((cmd & 0x40) ? 0x02 : 0) | | ||
| 57 | ((cmd & 0x80) ? 0x01 : 0); | ||
| 58 | 51 | ||
| 59 | dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n", | 52 | dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n", |
| 60 | cmd, scancode); | 53 | cmd, scancode); |
| 61 | 54 | ||
| 62 | *ir_key = scancode; | 55 | *protocol = RC_TYPE_OTHER; |
| 63 | *ir_raw = scancode; | 56 | *pscancode = scancode; |
| 57 | *toggle = 0; | ||
| 64 | return 1; | 58 | return 1; |
| 65 | } | 59 | } |
| 66 | 60 | ||
| @@ -97,7 +91,7 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
| 97 | dev->init_data.get_key = get_key_isdbt; | 91 | dev->init_data.get_key = get_key_isdbt; |
| 98 | dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name; | 92 | dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name; |
| 99 | /* The i2c micro-controller only outputs the cmd part of NEC protocol */ | 93 | /* The i2c micro-controller only outputs the cmd part of NEC protocol */ |
| 100 | dev->init_data.rc_dev->scanmask = 0xff; | 94 | dev->init_data.rc_dev->scancode_mask = 0xff; |
| 101 | dev->init_data.rc_dev->driver_name = "cx231xx"; | 95 | dev->init_data.rc_dev->driver_name = "cx231xx"; |
| 102 | dev->init_data.type = RC_BIT_NEC; | 96 | dev->init_data.type = RC_BIT_NEC; |
| 103 | info.addr = 0x30; | 97 | info.addr = 0x30; |
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c index 2a34ceee4802..3052c4c20229 100644 --- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c +++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c | |||
| @@ -654,8 +654,9 @@ static struct pcb_config cx231xx_Scenario[] = { | |||
| 654 | 654 | ||
| 655 | /*****************************************************************/ | 655 | /*****************************************************************/ |
| 656 | 656 | ||
| 657 | u32 initialize_cx231xx(struct cx231xx *dev) | 657 | int initialize_cx231xx(struct cx231xx *dev) |
| 658 | { | 658 | { |
| 659 | int retval; | ||
| 659 | u32 config_info = 0; | 660 | u32 config_info = 0; |
| 660 | struct pcb_config *p_pcb_info; | 661 | struct pcb_config *p_pcb_info; |
| 661 | u8 usb_speed = 1; /* from register,1--HS, 0--FS */ | 662 | u8 usb_speed = 1; /* from register,1--HS, 0--FS */ |
| @@ -670,7 +671,10 @@ u32 initialize_cx231xx(struct cx231xx *dev) | |||
| 670 | 671 | ||
| 671 | /* read board config register to find out which | 672 | /* read board config register to find out which |
| 672 | pcb config it is related to */ | 673 | pcb config it is related to */ |
| 673 | cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4); | 674 | retval = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, |
| 675 | data, 4); | ||
| 676 | if (retval < 0) | ||
| 677 | return retval; | ||
| 674 | 678 | ||
| 675 | config_info = le32_to_cpu(*((__le32 *)data)); | 679 | config_info = le32_to_cpu(*((__le32 *)data)); |
| 676 | usb_speed = (u8) (config_info & 0x1); | 680 | usb_speed = (u8) (config_info & 0x1); |
| @@ -767,7 +771,7 @@ u32 initialize_cx231xx(struct cx231xx *dev) | |||
| 767 | cx231xx_info("bad senario!!!!!\n"); | 771 | cx231xx_info("bad senario!!!!!\n"); |
| 768 | cx231xx_info("config_info=%x\n", | 772 | cx231xx_info("config_info=%x\n", |
| 769 | (config_info & SELFPOWER_MASK)); | 773 | (config_info & SELFPOWER_MASK)); |
| 770 | return 1; | 774 | return -ENODEV; |
| 771 | } | 775 | } |
| 772 | } | 776 | } |
| 773 | 777 | ||
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h index b3c6190e0c69..4511dc5d199c 100644 --- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h +++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h | |||
| @@ -221,6 +221,6 @@ enum INDEX_PCB_CONFIG{ | |||
| 221 | /***************************************************************************/ | 221 | /***************************************************************************/ |
| 222 | struct cx231xx; | 222 | struct cx231xx; |
| 223 | 223 | ||
| 224 | u32 initialize_cx231xx(struct cx231xx *p_dev); | 224 | int initialize_cx231xx(struct cx231xx *p_dev); |
| 225 | 225 | ||
| 226 | #endif | 226 | #endif |
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index 1f8751379e24..3b3ada6562ca 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c | |||
| @@ -208,7 +208,7 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, | |||
| 208 | static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) | 208 | static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) |
| 209 | { | 209 | { |
| 210 | struct cx231xx_dmaqueue *dma_q = urb->context; | 210 | struct cx231xx_dmaqueue *dma_q = urb->context; |
| 211 | int i, rc = 1; | 211 | int i; |
| 212 | unsigned char *p_buffer; | 212 | unsigned char *p_buffer; |
| 213 | u32 bytes_parsed = 0, buffer_size = 0; | 213 | u32 bytes_parsed = 0, buffer_size = 0; |
| 214 | u8 sav_eav = 0; | 214 | u8 sav_eav = 0; |
| @@ -299,13 +299,12 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) | |||
| 299 | bytes_parsed = 0; | 299 | bytes_parsed = 0; |
| 300 | 300 | ||
| 301 | } | 301 | } |
| 302 | return rc; | 302 | return 1; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) | 305 | static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) |
| 306 | { | 306 | { |
| 307 | struct cx231xx_dmaqueue *dma_q = urb->context; | 307 | struct cx231xx_dmaqueue *dma_q = urb->context; |
| 308 | int rc = 1; | ||
| 309 | unsigned char *p_buffer; | 308 | unsigned char *p_buffer; |
| 310 | u32 bytes_parsed = 0, buffer_size = 0; | 309 | u32 bytes_parsed = 0, buffer_size = 0; |
| 311 | u8 sav_eav = 0; | 310 | u8 sav_eav = 0; |
| @@ -379,7 +378,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) | |||
| 379 | bytes_parsed = 0; | 378 | bytes_parsed = 0; |
| 380 | 379 | ||
| 381 | } | 380 | } |
| 382 | return rc; | 381 | return 1; |
| 383 | } | 382 | } |
| 384 | 383 | ||
| 385 | 384 | ||
| @@ -886,7 +885,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
| 886 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 885 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 887 | 886 | ||
| 888 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | 887 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; |
| 889 | f->fmt.pix.priv = 0; | ||
| 890 | 888 | ||
| 891 | return 0; | 889 | return 0; |
| 892 | } | 890 | } |
| @@ -931,7 +929,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 931 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; | 929 | f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; |
| 932 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 930 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 933 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | 931 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; |
| 934 | f->fmt.pix.priv = 0; | ||
| 935 | 932 | ||
| 936 | return 0; | 933 | return 0; |
| 937 | } | 934 | } |
| @@ -1620,7 +1617,7 @@ static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner | |||
| 1620 | */ | 1617 | */ |
| 1621 | static int cx231xx_v4l2_open(struct file *filp) | 1618 | static int cx231xx_v4l2_open(struct file *filp) |
| 1622 | { | 1619 | { |
| 1623 | int errCode = 0, radio = 0; | 1620 | int radio = 0; |
| 1624 | struct video_device *vdev = video_devdata(filp); | 1621 | struct video_device *vdev = video_devdata(filp); |
| 1625 | struct cx231xx *dev = video_drvdata(filp); | 1622 | struct cx231xx *dev = video_drvdata(filp); |
| 1626 | struct cx231xx_fh *fh; | 1623 | struct cx231xx_fh *fh; |
| @@ -1718,7 +1715,7 @@ static int cx231xx_v4l2_open(struct file *filp) | |||
| 1718 | mutex_unlock(&dev->lock); | 1715 | mutex_unlock(&dev->lock); |
| 1719 | v4l2_fh_add(&fh->fh); | 1716 | v4l2_fh_add(&fh->fh); |
| 1720 | 1717 | ||
| 1721 | return errCode; | 1718 | return 0; |
| 1722 | } | 1719 | } |
| 1723 | 1720 | ||
| 1724 | /* | 1721 | /* |
| @@ -2066,7 +2063,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev, | |||
| 2066 | vfd->release = video_device_release; | 2063 | vfd->release = video_device_release; |
| 2067 | vfd->debug = video_debug; | 2064 | vfd->debug = video_debug; |
| 2068 | vfd->lock = &dev->lock; | 2065 | vfd->lock = &dev->lock; |
| 2069 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
| 2070 | 2066 | ||
| 2071 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); | 2067 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); |
| 2072 | 2068 | ||
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h index babca7fb85e2..aeb1bf42b88d 100644 --- a/drivers/media/usb/cx231xx/cx231xx.h +++ b/drivers/media/usb/cx231xx/cx231xx.h | |||
| @@ -73,6 +73,8 @@ | |||
| 73 | #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16 | 73 | #define CX231XX_BOARD_ELGATO_VIDEO_CAPTURE_V2 16 |
| 74 | #define CX231XX_BOARD_OTG102 17 | 74 | #define CX231XX_BOARD_OTG102 17 |
| 75 | #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 | 75 | #define CX231XX_BOARD_KWORLD_UB445_USB_HYBRID 18 |
| 76 | #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx 19 | ||
| 77 | #define CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx 20 | ||
| 76 | 78 | ||
| 77 | /* Limits minimum and default number of buffers */ | 79 | /* Limits minimum and default number of buffers */ |
| 78 | #define CX231XX_MIN_BUF 4 | 80 | #define CX231XX_MIN_BUF 4 |
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index 037e519bbaa2..66645b02c854 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig | |||
| @@ -129,6 +129,7 @@ config DVB_USB_RTL28XXU | |||
| 129 | depends on DVB_USB_V2 && I2C_MUX | 129 | depends on DVB_USB_V2 && I2C_MUX |
| 130 | select DVB_RTL2830 | 130 | select DVB_RTL2830 |
| 131 | select DVB_RTL2832 | 131 | select DVB_RTL2832 |
| 132 | select DVB_RTL2832_SDR if (MEDIA_SUBDRV_AUTOSELECT && MEDIA_SDR_SUPPORT) | ||
| 132 | select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT | 133 | select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT |
| 133 | select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT | 134 | select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT |
| 134 | select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT | 135 | select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT |
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c index da47d2392f2a..5ca738ab44e0 100644 --- a/drivers/media/usb/dvb-usb-v2/af9015.c +++ b/drivers/media/usb/dvb-usb-v2/af9015.c | |||
| @@ -1213,7 +1213,7 @@ static int af9015_rc_query(struct dvb_usb_device *d) | |||
| 1213 | if ((state->rc_repeat != buf[6] || buf[0]) && | 1213 | if ((state->rc_repeat != buf[6] || buf[0]) && |
| 1214 | !memcmp(&buf[12], state->rc_last, 4)) { | 1214 | !memcmp(&buf[12], state->rc_last, 4)) { |
| 1215 | dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__); | 1215 | dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__); |
| 1216 | rc_keydown(d->rc_dev, state->rc_keycode, 0); | 1216 | rc_repeat(d->rc_dev); |
| 1217 | state->rc_repeat = buf[6]; | 1217 | state->rc_repeat = buf[6]; |
| 1218 | return ret; | 1218 | return ret; |
| 1219 | } | 1219 | } |
| @@ -1233,18 +1233,22 @@ static int af9015_rc_query(struct dvb_usb_device *d) | |||
| 1233 | if (buf[14] == (u8) ~buf[15]) { | 1233 | if (buf[14] == (u8) ~buf[15]) { |
| 1234 | if (buf[12] == (u8) ~buf[13]) { | 1234 | if (buf[12] == (u8) ~buf[13]) { |
| 1235 | /* NEC */ | 1235 | /* NEC */ |
| 1236 | state->rc_keycode = buf[12] << 8 | buf[14]; | 1236 | state->rc_keycode = RC_SCANCODE_NEC(buf[12], |
| 1237 | buf[14]); | ||
| 1237 | } else { | 1238 | } else { |
| 1238 | /* NEC extended*/ | 1239 | /* NEC extended*/ |
| 1239 | state->rc_keycode = buf[12] << 16 | | 1240 | state->rc_keycode = RC_SCANCODE_NECX(buf[12] << 8 | |
| 1240 | buf[13] << 8 | buf[14]; | 1241 | buf[13], |
| 1242 | buf[14]); | ||
| 1241 | } | 1243 | } |
| 1242 | } else { | 1244 | } else { |
| 1243 | /* 32 bit NEC */ | 1245 | /* 32 bit NEC */ |
| 1244 | state->rc_keycode = buf[12] << 24 | buf[13] << 16 | | 1246 | state->rc_keycode = RC_SCANCODE_NEC32(buf[12] << 24 | |
| 1245 | buf[14] << 8 | buf[15]; | 1247 | buf[13] << 16 | |
| 1248 | buf[14] << 8 | | ||
| 1249 | buf[15]); | ||
| 1246 | } | 1250 | } |
| 1247 | rc_keydown(d->rc_dev, state->rc_keycode, 0); | 1251 | rc_keydown(d->rc_dev, RC_TYPE_NEC, state->rc_keycode, 0); |
| 1248 | } else { | 1252 | } else { |
| 1249 | dev_dbg(&d->udev->dev, "%s: no key press\n", __func__); | 1253 | dev_dbg(&d->udev->dev, "%s: no key press\n", __func__); |
| 1250 | /* Invalidate last keypress */ | 1254 | /* Invalidate last keypress */ |
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 7b9b75f60774..75ec1c659fdd 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c | |||
| @@ -799,6 +799,25 @@ static int af9035_read_config(struct dvb_usb_device *d) | |||
| 799 | addr += 0x10; /* shift for the 2nd tuner params */ | 799 | addr += 0x10; /* shift for the 2nd tuner params */ |
| 800 | } | 800 | } |
| 801 | 801 | ||
| 802 | /* | ||
| 803 | * These AVerMedia devices has a bad EEPROM content :-( | ||
| 804 | * Override some wrong values here. | ||
| 805 | */ | ||
| 806 | if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA) { | ||
| 807 | switch (le16_to_cpu(d->udev->descriptor.idProduct)) { | ||
| 808 | case USB_PID_AVERMEDIA_A835B_1835: | ||
| 809 | case USB_PID_AVERMEDIA_A835B_2835: | ||
| 810 | case USB_PID_AVERMEDIA_A835B_3835: | ||
| 811 | dev_info(&d->udev->dev, | ||
| 812 | "%s: overriding tuner from %02x to %02x\n", | ||
| 813 | KBUILD_MODNAME, state->af9033_config[0].tuner, | ||
| 814 | AF9033_TUNER_IT9135_60); | ||
| 815 | |||
| 816 | state->af9033_config[0].tuner = AF9033_TUNER_IT9135_60; | ||
| 817 | break; | ||
| 818 | } | ||
| 819 | } | ||
| 820 | |||
| 802 | skip_eeprom: | 821 | skip_eeprom: |
| 803 | /* get demod clock */ | 822 | /* get demod clock */ |
| 804 | ret = af9035_rd_reg(d, 0x00d800, &tmp); | 823 | ret = af9035_rd_reg(d, 0x00d800, &tmp); |
| @@ -1313,19 +1332,20 @@ static int af9035_rc_query(struct dvb_usb_device *d) | |||
| 1313 | if ((buf[2] + buf[3]) == 0xff) { | 1332 | if ((buf[2] + buf[3]) == 0xff) { |
| 1314 | if ((buf[0] + buf[1]) == 0xff) { | 1333 | if ((buf[0] + buf[1]) == 0xff) { |
| 1315 | /* NEC standard 16bit */ | 1334 | /* NEC standard 16bit */ |
| 1316 | key = buf[0] << 8 | buf[2]; | 1335 | key = RC_SCANCODE_NEC(buf[0], buf[2]); |
| 1317 | } else { | 1336 | } else { |
| 1318 | /* NEC extended 24bit */ | 1337 | /* NEC extended 24bit */ |
| 1319 | key = buf[0] << 16 | buf[1] << 8 | buf[2]; | 1338 | key = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], buf[2]); |
| 1320 | } | 1339 | } |
| 1321 | } else { | 1340 | } else { |
| 1322 | /* NEC full code 32bit */ | 1341 | /* NEC full code 32bit */ |
| 1323 | key = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; | 1342 | key = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 | |
| 1343 | buf[2] << 8 | buf[3]); | ||
| 1324 | } | 1344 | } |
| 1325 | 1345 | ||
| 1326 | dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf); | 1346 | dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 4, buf); |
| 1327 | 1347 | ||
| 1328 | rc_keydown(d->rc_dev, key, 0); | 1348 | rc_keydown(d->rc_dev, RC_TYPE_NEC, key, 0); |
| 1329 | 1349 | ||
| 1330 | return 0; | 1350 | return 0; |
| 1331 | 1351 | ||
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c index eeab79bdd2aa..e4a2382196f0 100644 --- a/drivers/media/usb/dvb-usb-v2/anysee.c +++ b/drivers/media/usb/dvb-usb-v2/anysee.c | |||
| @@ -1038,7 +1038,8 @@ static int anysee_rc_query(struct dvb_usb_device *d) | |||
| 1038 | if (ircode[0]) { | 1038 | if (ircode[0]) { |
| 1039 | dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__, | 1039 | dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__, |
| 1040 | ircode[1]); | 1040 | ircode[1]); |
| 1041 | rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0); | 1041 | rc_keydown(d->rc_dev, RC_TYPE_NEC, |
| 1042 | RC_SCANCODE_NEC(0x08, ircode[1]), 0); | ||
| 1042 | } | 1043 | } |
| 1043 | 1044 | ||
| 1044 | return 0; | 1045 | return 0; |
diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c index c3c4b98733bf..935dbaa80ef0 100644 --- a/drivers/media/usb/dvb-usb-v2/az6007.c +++ b/drivers/media/usb/dvb-usb-v2/az6007.c | |||
| @@ -207,24 +207,27 @@ static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff) | |||
| 207 | static int az6007_rc_query(struct dvb_usb_device *d) | 207 | static int az6007_rc_query(struct dvb_usb_device *d) |
| 208 | { | 208 | { |
| 209 | struct az6007_device_state *st = d_to_priv(d); | 209 | struct az6007_device_state *st = d_to_priv(d); |
| 210 | unsigned code = 0; | 210 | unsigned code; |
| 211 | 211 | ||
| 212 | az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); | 212 | az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10); |
| 213 | 213 | ||
| 214 | if (st->data[1] == 0x44) | 214 | if (st->data[1] == 0x44) |
| 215 | return 0; | 215 | return 0; |
| 216 | 216 | ||
| 217 | if ((st->data[1] ^ st->data[2]) == 0xff) | 217 | if ((st->data[3] ^ st->data[4]) == 0xff) { |
| 218 | code = st->data[1]; | 218 | if ((st->data[1] ^ st->data[2]) == 0xff) |
| 219 | else | 219 | code = RC_SCANCODE_NEC(st->data[1], st->data[3]); |
| 220 | code = st->data[1] << 8 | st->data[2]; | 220 | else |
| 221 | 221 | code = RC_SCANCODE_NECX(st->data[1] << 8 | st->data[2], | |
| 222 | if ((st->data[3] ^ st->data[4]) == 0xff) | 222 | st->data[3]); |
| 223 | code = code << 8 | st->data[3]; | 223 | } else { |
| 224 | else | 224 | code = RC_SCANCODE_NEC32(st->data[1] << 24 | |
| 225 | code = code << 16 | st->data[3] << 8 | st->data[4]; | 225 | st->data[2] << 16 | |
| 226 | st->data[3] << 8 | | ||
| 227 | st->data[4]); | ||
| 228 | } | ||
| 226 | 229 | ||
| 227 | rc_keydown(d->rc_dev, code, st->data[5]); | 230 | rc_keydown(d->rc_dev, RC_TYPE_NEC, code, st->data[5]); |
| 228 | 231 | ||
| 229 | return 0; | 232 | return 0; |
| 230 | } | 233 | } |
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index f296394bb7c5..2e90310be2af 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | |||
| @@ -164,7 +164,7 @@ static int dvb_usbv2_remote_init(struct dvb_usb_device *d) | |||
| 164 | dev->driver_name = (char *) d->props->driver_name; | 164 | dev->driver_name = (char *) d->props->driver_name; |
| 165 | dev->map_name = d->rc.map_name; | 165 | dev->map_name = d->rc.map_name; |
| 166 | dev->driver_type = d->rc.driver_type; | 166 | dev->driver_type = d->rc.driver_type; |
| 167 | rc_set_allowed_protocols(dev, d->rc.allowed_protos); | 167 | dev->allowed_protocols = d->rc.allowed_protos; |
| 168 | dev->change_protocol = d->rc.change_protocol; | 168 | dev->change_protocol = d->rc.change_protocol; |
| 169 | dev->priv = d; | 169 | dev->priv = d; |
| 170 | 170 | ||
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index f674dc024d06..e332af731187 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c | |||
| @@ -125,14 +125,13 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
| 125 | #define TUNER_RS2000 0x4 | 125 | #define TUNER_RS2000 0x4 |
| 126 | 126 | ||
| 127 | struct lme2510_state { | 127 | struct lme2510_state { |
| 128 | unsigned long int_urb_due; | ||
| 128 | u8 id; | 129 | u8 id; |
| 129 | u8 tuner_config; | 130 | u8 tuner_config; |
| 130 | u8 signal_lock; | 131 | u8 signal_lock; |
| 131 | u8 signal_level; | 132 | u8 signal_level; |
| 132 | u8 signal_sn; | 133 | u8 signal_sn; |
| 133 | u8 time_key; | 134 | u8 time_key; |
| 134 | u8 last_key; | ||
| 135 | u8 key_timeout; | ||
| 136 | u8 i2c_talk_onoff; | 135 | u8 i2c_talk_onoff; |
| 137 | u8 i2c_gate; | 136 | u8 i2c_gate; |
| 138 | u8 i2c_tuner_gate_w; | 137 | u8 i2c_tuner_gate_w; |
| @@ -287,14 +286,13 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
| 287 | case 0xaa: | 286 | case 0xaa: |
| 288 | debug_data_snipet(1, "INT Remote data snipet", ibuf); | 287 | debug_data_snipet(1, "INT Remote data snipet", ibuf); |
| 289 | if ((ibuf[4] + ibuf[5]) == 0xff) { | 288 | if ((ibuf[4] + ibuf[5]) == 0xff) { |
| 290 | key = ibuf[5]; | 289 | key = RC_SCANCODE_NECX((ibuf[2] ^ 0xff) << 8 | |
| 291 | key += (ibuf[3] > 0) | 290 | (ibuf[3] > 0) ? (ibuf[3] ^ 0xff) : 0, |
| 292 | ? (ibuf[3] ^ 0xff) << 8 : 0; | 291 | ibuf[5]); |
| 293 | key += (ibuf[2] ^ 0xff) << 16; | ||
| 294 | deb_info(1, "INT Key =%08x", key); | 292 | deb_info(1, "INT Key =%08x", key); |
| 295 | if (adap_to_d(adap)->rc_dev != NULL) | 293 | if (adap_to_d(adap)->rc_dev != NULL) |
| 296 | rc_keydown(adap_to_d(adap)->rc_dev, | 294 | rc_keydown(adap_to_d(adap)->rc_dev, |
| 297 | key, 0); | 295 | RC_TYPE_NEC, key, 0); |
| 298 | } | 296 | } |
| 299 | break; | 297 | break; |
| 300 | case 0xbb: | 298 | case 0xbb: |
| @@ -323,7 +321,7 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
| 323 | } | 321 | } |
| 324 | break; | 322 | break; |
| 325 | case TUNER_RS2000: | 323 | case TUNER_RS2000: |
| 326 | if (ibuf[1] == 0x3 && ibuf[6] == 0xff) | 324 | if (ibuf[2] & 0x1) |
| 327 | st->signal_lock = 0xff; | 325 | st->signal_lock = 0xff; |
| 328 | else | 326 | else |
| 329 | st->signal_lock = 0x00; | 327 | st->signal_lock = 0x00; |
| @@ -343,7 +341,12 @@ static void lme2510_int_response(struct urb *lme_urb) | |||
| 343 | break; | 341 | break; |
| 344 | } | 342 | } |
| 345 | } | 343 | } |
| 344 | |||
| 346 | usb_submit_urb(lme_urb, GFP_ATOMIC); | 345 | usb_submit_urb(lme_urb, GFP_ATOMIC); |
| 346 | |||
| 347 | /* interrupt urb is due every 48 msecs while streaming | ||
| 348 | * add 12msecs for system lag */ | ||
| 349 | st->int_urb_due = jiffies + msecs_to_jiffies(60); | ||
| 347 | } | 350 | } |
| 348 | 351 | ||
| 349 | static int lme2510_int_read(struct dvb_usb_adapter *adap) | 352 | static int lme2510_int_read(struct dvb_usb_adapter *adap) |
| @@ -584,14 +587,13 @@ static int lme2510_msg(struct dvb_usb_device *d, | |||
| 584 | switch (wbuf[3]) { | 587 | switch (wbuf[3]) { |
| 585 | case 0x8c: | 588 | case 0x8c: |
| 586 | rbuf[0] = 0x55; | 589 | rbuf[0] = 0x55; |
| 587 | rbuf[1] = 0xff; | 590 | rbuf[1] = st->signal_lock; |
| 588 | if (st->last_key == st->time_key) { | 591 | |
| 589 | st->key_timeout++; | 592 | /* If int_urb_due overdue |
| 590 | if (st->key_timeout > 5) | 593 | * set rbuf[1] to 0 to clear lock */ |
| 591 | rbuf[1] = 0; | 594 | if (time_after(jiffies, st->int_urb_due)) |
| 592 | } else | 595 | rbuf[1] = 0; |
| 593 | st->key_timeout = 0; | 596 | |
| 594 | st->last_key = st->time_key; | ||
| 595 | break; | 597 | break; |
| 596 | default: | 598 | default: |
| 597 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); | 599 | lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen); |
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index c7304fa8ab73..b8a707e57b99 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c | |||
| @@ -129,7 +129,7 @@ int mxl111sf_write_reg_mask(struct mxl111sf_state *state, | |||
| 129 | u8 addr, u8 mask, u8 data) | 129 | u8 addr, u8 mask, u8 data) |
| 130 | { | 130 | { |
| 131 | int ret; | 131 | int ret; |
| 132 | u8 val; | 132 | u8 val = 0; |
| 133 | 133 | ||
| 134 | if (mask != 0xff) { | 134 | if (mask != 0xff) { |
| 135 | ret = mxl111sf_read_reg(state, addr, &val); | 135 | ret = mxl111sf_read_reg(state, addr, &val); |
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index a676e4452847..27b1e0397e71 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c | |||
| @@ -1287,19 +1287,19 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d) | |||
| 1287 | if (buf[2] == (u8) ~buf[3]) { | 1287 | if (buf[2] == (u8) ~buf[3]) { |
| 1288 | if (buf[0] == (u8) ~buf[1]) { | 1288 | if (buf[0] == (u8) ~buf[1]) { |
| 1289 | /* NEC standard (16 bit) */ | 1289 | /* NEC standard (16 bit) */ |
| 1290 | rc_code = buf[0] << 8 | buf[2]; | 1290 | rc_code = RC_SCANCODE_NEC(buf[0], buf[2]); |
| 1291 | } else { | 1291 | } else { |
| 1292 | /* NEC extended (24 bit) */ | 1292 | /* NEC extended (24 bit) */ |
| 1293 | rc_code = buf[0] << 16 | | 1293 | rc_code = RC_SCANCODE_NECX(buf[0] << 8 | buf[1], |
| 1294 | buf[1] << 8 | buf[2]; | 1294 | buf[2]); |
| 1295 | } | 1295 | } |
| 1296 | } else { | 1296 | } else { |
| 1297 | /* NEC full (32 bit) */ | 1297 | /* NEC full (32 bit) */ |
| 1298 | rc_code = buf[0] << 24 | buf[1] << 16 | | 1298 | rc_code = RC_SCANCODE_NEC32(buf[0] << 24 | buf[1] << 16 | |
| 1299 | buf[2] << 8 | buf[3]; | 1299 | buf[2] << 8 | buf[3]); |
| 1300 | } | 1300 | } |
| 1301 | 1301 | ||
| 1302 | rc_keydown(d->rc_dev, rc_code, 0); | 1302 | rc_keydown(d->rc_dev, RC_TYPE_NEC, rc_code, 0); |
| 1303 | 1303 | ||
| 1304 | ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); | 1304 | ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1); |
| 1305 | if (ret) | 1305 | if (ret) |
| @@ -1541,6 +1541,8 @@ static const struct usb_device_id rtl28xxu_id_table[] = { | |||
| 1541 | &rtl2832u_props, "Peak DVB-T USB", NULL) }, | 1541 | &rtl2832u_props, "Peak DVB-T USB", NULL) }, |
| 1542 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U, | 1542 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20_RTL2832U, |
| 1543 | &rtl2832u_props, "Sveon STV20", NULL) }, | 1543 | &rtl2832u_props, "Sveon STV20", NULL) }, |
| 1544 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV21, | ||
| 1545 | &rtl2832u_props, "Sveon STV21", NULL) }, | ||
| 1544 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27, | 1546 | { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV27, |
| 1545 | &rtl2832u_props, "Sveon STV27", NULL) }, | 1547 | &rtl2832u_props, "Sveon STV27", NULL) }, |
| 1546 | 1548 | ||
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig index c5d95662e2e1..10aef2188fbe 100644 --- a/drivers/media/usb/dvb-usb/Kconfig +++ b/drivers/media/usb/dvb-usb/Kconfig | |||
| @@ -117,10 +117,12 @@ config DVB_USB_CXUSB | |||
| 117 | select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT | 117 | select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT |
| 118 | select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT | 118 | select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT |
| 119 | select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT | 119 | select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT |
| 120 | select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT | ||
| 120 | select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT | 121 | select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT |
| 121 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT | 122 | select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT |
| 122 | select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT | 123 | select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT |
| 123 | select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT | 124 | select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT |
| 125 | select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT | ||
| 124 | help | 126 | help |
| 125 | Say Y here to support the Conexant USB2.0 hybrid reference design. | 127 | Say Y here to support the Conexant USB2.0 hybrid reference design. |
| 126 | Currently, only DVB and ATSC modes are supported, analog mode | 128 | Currently, only DVB and ATSC modes are supported, analog mode |
| @@ -128,6 +130,7 @@ config DVB_USB_CXUSB | |||
| 128 | 130 | ||
| 129 | Medion MD95700 hybrid USB2.0 device. | 131 | Medion MD95700 hybrid USB2.0 device. |
| 130 | DViCO FusionHDTV (Bluebird) USB2.0 devices | 132 | DViCO FusionHDTV (Bluebird) USB2.0 devices |
| 133 | TechnoTrend TVStick CT2-4400 | ||
| 131 | 134 | ||
| 132 | config DVB_USB_M920X | 135 | config DVB_USB_M920X |
| 133 | tristate "Uli m920x DVB-T USB2.0 support" | 136 | tristate "Uli m920x DVB-T USB2.0 support" |
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index a1c641e18362..16bc579d1404 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c | |||
| @@ -42,9 +42,11 @@ | |||
| 42 | #include "dib0070.h" | 42 | #include "dib0070.h" |
| 43 | #include "lgs8gxx.h" | 43 | #include "lgs8gxx.h" |
| 44 | #include "atbm8830.h" | 44 | #include "atbm8830.h" |
| 45 | #include "si2168.h" | ||
| 46 | #include "si2157.h" | ||
| 45 | 47 | ||
| 46 | /* Max transfer size done by I2C transfer functions */ | 48 | /* Max transfer size done by I2C transfer functions */ |
| 47 | #define MAX_XFER_SIZE 64 | 49 | #define MAX_XFER_SIZE 80 |
| 48 | 50 | ||
| 49 | /* debug */ | 51 | /* debug */ |
| 50 | static int dvb_usb_cxusb_debug; | 52 | static int dvb_usb_cxusb_debug; |
| @@ -144,6 +146,22 @@ static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d, | |||
| 144 | } | 146 | } |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 149 | static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff) | ||
| 150 | { | ||
| 151 | u8 o[2], i; | ||
| 152 | int rc; | ||
| 153 | |||
| 154 | o[0] = 0x83; | ||
| 155 | o[1] = onoff; | ||
| 156 | rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1); | ||
| 157 | |||
| 158 | if (rc) { | ||
| 159 | deb_info("gpio_write failed.\n"); | ||
| 160 | return -EIO; | ||
| 161 | } | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 147 | /* I2C */ | 165 | /* I2C */ |
| 148 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | 166 | static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], |
| 149 | int num) | 167 | int num) |
| @@ -505,6 +523,30 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event, | |||
| 505 | return 0; | 523 | return 0; |
| 506 | } | 524 | } |
| 507 | 525 | ||
| 526 | static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d) | ||
| 527 | { | ||
| 528 | u8 i[2]; | ||
| 529 | int ret; | ||
| 530 | u32 cmd, keycode; | ||
| 531 | u8 rc5_cmd, rc5_addr, rc5_toggle; | ||
| 532 | |||
| 533 | ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2); | ||
| 534 | if (ret) | ||
| 535 | return ret; | ||
| 536 | |||
| 537 | cmd = (i[0] << 8) | i[1]; | ||
| 538 | |||
| 539 | if (cmd != 0xffff) { | ||
| 540 | rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */ | ||
| 541 | rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */ | ||
| 542 | rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */ | ||
| 543 | keycode = (rc5_addr << 8) | rc5_cmd; | ||
| 544 | rc_keydown(d->rc_dev, RC_BIT_RC5, keycode, rc5_toggle); | ||
| 545 | } | ||
| 546 | |||
| 547 | return 0; | ||
| 548 | } | ||
| 549 | |||
| 508 | static struct rc_map_table rc_map_dvico_mce_table[] = { | 550 | static struct rc_map_table rc_map_dvico_mce_table[] = { |
| 509 | { 0xfe02, KEY_TV }, | 551 | { 0xfe02, KEY_TV }, |
| 510 | { 0xfe0e, KEY_MP3 }, | 552 | { 0xfe0e, KEY_MP3 }, |
| @@ -1070,8 +1112,15 @@ static struct dib7000p_config cxusb_dualdig4_rev2_config = { | |||
| 1070 | .hostbus_diversity = 1, | 1112 | .hostbus_diversity = 1, |
| 1071 | }; | 1113 | }; |
| 1072 | 1114 | ||
| 1115 | struct dib0700_adapter_state { | ||
| 1116 | int (*set_param_save)(struct dvb_frontend *); | ||
| 1117 | struct dib7000p_ops dib7000p_ops; | ||
| 1118 | }; | ||
| 1119 | |||
| 1073 | static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | 1120 | static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) |
| 1074 | { | 1121 | { |
| 1122 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1123 | |||
| 1075 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) | 1124 | if (usb_set_interface(adap->dev->udev, 0, 1) < 0) |
| 1076 | err("set interface failed"); | 1125 | err("set interface failed"); |
| 1077 | 1126 | ||
| @@ -1079,14 +1128,17 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1079 | 1128 | ||
| 1080 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); | 1129 | cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1); |
| 1081 | 1130 | ||
| 1082 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 1131 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) |
| 1083 | &cxusb_dualdig4_rev2_config) < 0) { | 1132 | return -ENODEV; |
| 1133 | |||
| 1134 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | ||
| 1135 | &cxusb_dualdig4_rev2_config) < 0) { | ||
| 1084 | printk(KERN_WARNING "Unable to enumerate dib7000p\n"); | 1136 | printk(KERN_WARNING "Unable to enumerate dib7000p\n"); |
| 1085 | return -ENODEV; | 1137 | return -ENODEV; |
| 1086 | } | 1138 | } |
| 1087 | 1139 | ||
| 1088 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | 1140 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, |
| 1089 | &cxusb_dualdig4_rev2_config); | 1141 | &cxusb_dualdig4_rev2_config); |
| 1090 | if (adap->fe_adap[0].fe == NULL) | 1142 | if (adap->fe_adap[0].fe == NULL) |
| 1091 | return -EIO; | 1143 | return -EIO; |
| 1092 | 1144 | ||
| @@ -1095,7 +1147,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1095 | 1147 | ||
| 1096 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | 1148 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) |
| 1097 | { | 1149 | { |
| 1098 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | 1150 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
| 1151 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1152 | |||
| 1153 | return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff); | ||
| 1099 | } | 1154 | } |
| 1100 | 1155 | ||
| 1101 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | 1156 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) |
| @@ -1110,10 +1165,6 @@ static struct dib0070_config dib7070p_dib0070_config = { | |||
| 1110 | .clock_khz = 12000, | 1165 | .clock_khz = 12000, |
| 1111 | }; | 1166 | }; |
| 1112 | 1167 | ||
| 1113 | struct dib0700_adapter_state { | ||
| 1114 | int (*set_param_save) (struct dvb_frontend *); | ||
| 1115 | }; | ||
| 1116 | |||
| 1117 | static int dib7070_set_param_override(struct dvb_frontend *fe) | 1168 | static int dib7070_set_param_override(struct dvb_frontend *fe) |
| 1118 | { | 1169 | { |
| 1119 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | 1170 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; |
| @@ -1128,7 +1179,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe) | |||
| 1128 | case BAND_UHF: offset = 550; break; | 1179 | case BAND_UHF: offset = 550; break; |
| 1129 | } | 1180 | } |
| 1130 | 1181 | ||
| 1131 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | 1182 | state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); |
| 1132 | 1183 | ||
| 1133 | return state->set_param_save(fe); | 1184 | return state->set_param_save(fe); |
| 1134 | } | 1185 | } |
| @@ -1136,8 +1187,14 @@ static int dib7070_set_param_override(struct dvb_frontend *fe) | |||
| 1136 | static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) | 1187 | static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap) |
| 1137 | { | 1188 | { |
| 1138 | struct dib0700_adapter_state *st = adap->priv; | 1189 | struct dib0700_adapter_state *st = adap->priv; |
| 1139 | struct i2c_adapter *tun_i2c = | 1190 | struct i2c_adapter *tun_i2c; |
| 1140 | dib7000p_get_i2c_master(adap->fe_adap[0].fe, | 1191 | |
| 1192 | /* | ||
| 1193 | * No need to call dvb7000p_attach here, as it was called | ||
| 1194 | * already, as frontend_attach method is called first, and | ||
| 1195 | * tuner_attach is only called on sucess. | ||
| 1196 | */ | ||
| 1197 | tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, | ||
| 1141 | DIBX000_I2C_INTERFACE_TUNER, 1); | 1198 | DIBX000_I2C_INTERFACE_TUNER, 1); |
| 1142 | 1199 | ||
| 1143 | if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, | 1200 | if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, |
| @@ -1286,6 +1343,74 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1286 | return 0; | 1343 | return 0; |
| 1287 | } | 1344 | } |
| 1288 | 1345 | ||
| 1346 | static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap) | ||
| 1347 | { | ||
| 1348 | struct dvb_usb_device *d = adap->dev; | ||
| 1349 | struct cxusb_state *st = d->priv; | ||
| 1350 | struct i2c_adapter *adapter; | ||
| 1351 | struct i2c_client *client_demod; | ||
| 1352 | struct i2c_client *client_tuner; | ||
| 1353 | struct i2c_board_info info; | ||
| 1354 | struct si2168_config si2168_config; | ||
| 1355 | struct si2157_config si2157_config; | ||
| 1356 | |||
| 1357 | /* reset the tuner */ | ||
| 1358 | if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) { | ||
| 1359 | err("clear tuner gpio failed"); | ||
| 1360 | return -EIO; | ||
| 1361 | } | ||
| 1362 | msleep(100); | ||
| 1363 | if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) { | ||
| 1364 | err("set tuner gpio failed"); | ||
| 1365 | return -EIO; | ||
| 1366 | } | ||
| 1367 | msleep(100); | ||
| 1368 | |||
| 1369 | /* attach frontend */ | ||
| 1370 | si2168_config.i2c_adapter = &adapter; | ||
| 1371 | si2168_config.fe = &adap->fe_adap[0].fe; | ||
| 1372 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
| 1373 | strlcpy(info.type, "si2168", I2C_NAME_SIZE); | ||
| 1374 | info.addr = 0x64; | ||
| 1375 | info.platform_data = &si2168_config; | ||
| 1376 | request_module(info.type); | ||
| 1377 | client_demod = i2c_new_device(&d->i2c_adap, &info); | ||
| 1378 | if (client_demod == NULL || client_demod->dev.driver == NULL) | ||
| 1379 | return -ENODEV; | ||
| 1380 | |||
| 1381 | if (!try_module_get(client_demod->dev.driver->owner)) { | ||
| 1382 | i2c_unregister_device(client_demod); | ||
| 1383 | return -ENODEV; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | st->i2c_client_demod = client_demod; | ||
| 1387 | |||
| 1388 | /* attach tuner */ | ||
| 1389 | memset(&si2157_config, 0, sizeof(si2157_config)); | ||
| 1390 | si2157_config.fe = adap->fe_adap[0].fe; | ||
| 1391 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
| 1392 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); | ||
| 1393 | info.addr = 0x60; | ||
| 1394 | info.platform_data = &si2157_config; | ||
| 1395 | request_module(info.type); | ||
| 1396 | client_tuner = i2c_new_device(adapter, &info); | ||
| 1397 | if (client_tuner == NULL || client_tuner->dev.driver == NULL) { | ||
| 1398 | module_put(client_demod->dev.driver->owner); | ||
| 1399 | i2c_unregister_device(client_demod); | ||
| 1400 | return -ENODEV; | ||
| 1401 | } | ||
| 1402 | if (!try_module_get(client_tuner->dev.driver->owner)) { | ||
| 1403 | i2c_unregister_device(client_tuner); | ||
| 1404 | module_put(client_demod->dev.driver->owner); | ||
| 1405 | i2c_unregister_device(client_demod); | ||
| 1406 | return -ENODEV; | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | st->i2c_client_tuner = client_tuner; | ||
| 1410 | |||
| 1411 | return 0; | ||
| 1412 | } | ||
| 1413 | |||
| 1289 | /* | 1414 | /* |
| 1290 | * DViCO has shipped two devices with the same USB ID, but only one of them | 1415 | * DViCO has shipped two devices with the same USB ID, but only one of them |
| 1291 | * needs a firmware download. Check the device class details to see if they | 1416 | * needs a firmware download. Check the device class details to see if they |
| @@ -1367,6 +1492,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope | |||
| 1367 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; | 1492 | static struct dvb_usb_device_properties cxusb_aver_a868r_properties; |
| 1368 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; | 1493 | static struct dvb_usb_device_properties cxusb_d680_dmb_properties; |
| 1369 | static struct dvb_usb_device_properties cxusb_mygica_d689_properties; | 1494 | static struct dvb_usb_device_properties cxusb_mygica_d689_properties; |
| 1495 | static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties; | ||
| 1370 | 1496 | ||
| 1371 | static int cxusb_probe(struct usb_interface *intf, | 1497 | static int cxusb_probe(struct usb_interface *intf, |
| 1372 | const struct usb_device_id *id) | 1498 | const struct usb_device_id *id) |
| @@ -1397,12 +1523,37 @@ static int cxusb_probe(struct usb_interface *intf, | |||
| 1397 | THIS_MODULE, NULL, adapter_nr) || | 1523 | THIS_MODULE, NULL, adapter_nr) || |
| 1398 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, | 1524 | 0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, |
| 1399 | THIS_MODULE, NULL, adapter_nr) || | 1525 | THIS_MODULE, NULL, adapter_nr) || |
| 1526 | 0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties, | ||
| 1527 | THIS_MODULE, NULL, adapter_nr) || | ||
| 1400 | 0) | 1528 | 0) |
| 1401 | return 0; | 1529 | return 0; |
| 1402 | 1530 | ||
| 1403 | return -EINVAL; | 1531 | return -EINVAL; |
| 1404 | } | 1532 | } |
| 1405 | 1533 | ||
| 1534 | static void cxusb_disconnect(struct usb_interface *intf) | ||
| 1535 | { | ||
| 1536 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
| 1537 | struct cxusb_state *st = d->priv; | ||
| 1538 | struct i2c_client *client; | ||
| 1539 | |||
| 1540 | /* remove I2C client for tuner */ | ||
| 1541 | client = st->i2c_client_tuner; | ||
| 1542 | if (client) { | ||
| 1543 | module_put(client->dev.driver->owner); | ||
| 1544 | i2c_unregister_device(client); | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | /* remove I2C client for demodulator */ | ||
| 1548 | client = st->i2c_client_demod; | ||
| 1549 | if (client) { | ||
| 1550 | module_put(client->dev.driver->owner); | ||
| 1551 | i2c_unregister_device(client); | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | dvb_usb_device_exit(intf); | ||
| 1555 | } | ||
| 1556 | |||
| 1406 | static struct usb_device_id cxusb_table [] = { | 1557 | static struct usb_device_id cxusb_table [] = { |
| 1407 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, | 1558 | { USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) }, |
| 1408 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, | 1559 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) }, |
| @@ -1424,6 +1575,7 @@ static struct usb_device_id cxusb_table [] = { | |||
| 1424 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, | 1575 | { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) }, |
| 1425 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, | 1576 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) }, |
| 1426 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, | 1577 | { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) }, |
| 1578 | { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) }, | ||
| 1427 | {} /* Terminating entry */ | 1579 | {} /* Terminating entry */ |
| 1428 | }; | 1580 | }; |
| 1429 | MODULE_DEVICE_TABLE (usb, cxusb_table); | 1581 | MODULE_DEVICE_TABLE (usb, cxusb_table); |
| @@ -2070,10 +2222,63 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = { | |||
| 2070 | } | 2222 | } |
| 2071 | }; | 2223 | }; |
| 2072 | 2224 | ||
| 2225 | static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = { | ||
| 2226 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
| 2227 | |||
| 2228 | .usb_ctrl = CYPRESS_FX2, | ||
| 2229 | |||
| 2230 | .size_of_priv = sizeof(struct cxusb_state), | ||
| 2231 | |||
| 2232 | .num_adapters = 1, | ||
| 2233 | .adapter = { | ||
| 2234 | { | ||
| 2235 | .num_frontends = 1, | ||
| 2236 | .fe = {{ | ||
| 2237 | .streaming_ctrl = cxusb_streaming_ctrl, | ||
| 2238 | /* both frontend and tuner attached in the | ||
| 2239 | same function */ | ||
| 2240 | .frontend_attach = cxusb_tt_ct2_4400_attach, | ||
| 2241 | |||
| 2242 | /* parameter for the MPEG2-data transfer */ | ||
| 2243 | .stream = { | ||
| 2244 | .type = USB_BULK, | ||
| 2245 | .count = 8, | ||
| 2246 | .endpoint = 0x82, | ||
| 2247 | .u = { | ||
| 2248 | .bulk = { | ||
| 2249 | .buffersize = 4096, | ||
| 2250 | } | ||
| 2251 | } | ||
| 2252 | }, | ||
| 2253 | } }, | ||
| 2254 | }, | ||
| 2255 | }, | ||
| 2256 | |||
| 2257 | .i2c_algo = &cxusb_i2c_algo, | ||
| 2258 | .generic_bulk_ctrl_endpoint = 0x01, | ||
| 2259 | .generic_bulk_ctrl_endpoint_response = 0x81, | ||
| 2260 | |||
| 2261 | .rc.core = { | ||
| 2262 | .rc_codes = RC_MAP_TT_1500, | ||
| 2263 | .allowed_protos = RC_BIT_RC5, | ||
| 2264 | .rc_query = cxusb_tt_ct2_4400_rc_query, | ||
| 2265 | .rc_interval = 150, | ||
| 2266 | }, | ||
| 2267 | |||
| 2268 | .num_device_descs = 1, | ||
| 2269 | .devices = { | ||
| 2270 | { | ||
| 2271 | "TechnoTrend TVStick CT2-4400", | ||
| 2272 | { NULL }, | ||
| 2273 | { &cxusb_table[20], NULL }, | ||
| 2274 | }, | ||
| 2275 | } | ||
| 2276 | }; | ||
| 2277 | |||
| 2073 | static struct usb_driver cxusb_driver = { | 2278 | static struct usb_driver cxusb_driver = { |
| 2074 | .name = "dvb_usb_cxusb", | 2279 | .name = "dvb_usb_cxusb", |
| 2075 | .probe = cxusb_probe, | 2280 | .probe = cxusb_probe, |
| 2076 | .disconnect = dvb_usb_device_exit, | 2281 | .disconnect = cxusb_disconnect, |
| 2077 | .id_table = cxusb_table, | 2282 | .id_table = cxusb_table, |
| 2078 | }; | 2283 | }; |
| 2079 | 2284 | ||
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h index 1a51eafd31b9..527ff7905e15 100644 --- a/drivers/media/usb/dvb-usb/cxusb.h +++ b/drivers/media/usb/dvb-usb/cxusb.h | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | 30 | ||
| 31 | struct cxusb_state { | 31 | struct cxusb_state { |
| 32 | u8 gpio_write_state[3]; | 32 | u8 gpio_write_state[3]; |
| 33 | struct i2c_client *i2c_client_demod; | ||
| 34 | struct i2c_client *i2c_client_tuner; | ||
| 33 | }; | 35 | }; |
| 34 | 36 | ||
| 35 | #endif | 37 | #endif |
diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index c14285fa8271..50856dbf5496 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c | |||
| @@ -658,13 +658,8 @@ out: | |||
| 658 | struct dib0700_rc_response { | 658 | struct dib0700_rc_response { |
| 659 | u8 report_id; | 659 | u8 report_id; |
| 660 | u8 data_state; | 660 | u8 data_state; |
| 661 | union { | 661 | u8 system; |
| 662 | u16 system16; | 662 | u8 not_system; |
| 663 | struct { | ||
| 664 | u8 not_system; | ||
| 665 | u8 system; | ||
| 666 | }; | ||
| 667 | }; | ||
| 668 | u8 data; | 663 | u8 data; |
| 669 | u8 not_data; | 664 | u8 not_data; |
| 670 | }; | 665 | }; |
| @@ -674,6 +669,7 @@ static void dib0700_rc_urb_completion(struct urb *purb) | |||
| 674 | { | 669 | { |
| 675 | struct dvb_usb_device *d = purb->context; | 670 | struct dvb_usb_device *d = purb->context; |
| 676 | struct dib0700_rc_response *poll_reply; | 671 | struct dib0700_rc_response *poll_reply; |
| 672 | enum rc_type protocol; | ||
| 677 | u32 uninitialized_var(keycode); | 673 | u32 uninitialized_var(keycode); |
| 678 | u8 toggle; | 674 | u8 toggle; |
| 679 | 675 | ||
| @@ -707,44 +703,55 @@ static void dib0700_rc_urb_completion(struct urb *purb) | |||
| 707 | 703 | ||
| 708 | switch (d->props.rc.core.protocol) { | 704 | switch (d->props.rc.core.protocol) { |
| 709 | case RC_BIT_NEC: | 705 | case RC_BIT_NEC: |
| 706 | protocol = RC_TYPE_NEC; | ||
| 710 | toggle = 0; | 707 | toggle = 0; |
| 711 | 708 | ||
| 712 | /* NEC protocol sends repeat code as 0 0 0 FF */ | 709 | /* NEC protocol sends repeat code as 0 0 0 FF */ |
| 713 | if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00) | 710 | if (poll_reply->system == 0x00 && |
| 714 | && (poll_reply->not_data == 0xff)) { | 711 | poll_reply->not_system == 0x00 && |
| 712 | poll_reply->data == 0x00 && | ||
| 713 | poll_reply->not_data == 0xff) { | ||
| 715 | poll_reply->data_state = 2; | 714 | poll_reply->data_state = 2; |
| 716 | break; | 715 | break; |
| 717 | } | 716 | } |
| 718 | 717 | ||
| 719 | if ((poll_reply->system ^ poll_reply->not_system) != 0xff) { | 718 | if ((poll_reply->data ^ poll_reply->not_data) != 0xff) { |
| 719 | deb_data("NEC32 protocol\n"); | ||
| 720 | keycode = RC_SCANCODE_NEC32(poll_reply->system << 24 | | ||
| 721 | poll_reply->not_system << 16 | | ||
| 722 | poll_reply->data << 8 | | ||
| 723 | poll_reply->not_data); | ||
| 724 | } else if ((poll_reply->system ^ poll_reply->not_system) != 0xff) { | ||
| 720 | deb_data("NEC extended protocol\n"); | 725 | deb_data("NEC extended protocol\n"); |
| 721 | /* NEC extended code - 24 bits */ | 726 | keycode = RC_SCANCODE_NECX(poll_reply->system << 8 | |
| 722 | keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data; | 727 | poll_reply->not_system, |
| 728 | poll_reply->data); | ||
| 729 | |||
| 723 | } else { | 730 | } else { |
| 724 | deb_data("NEC normal protocol\n"); | 731 | deb_data("NEC normal protocol\n"); |
| 725 | /* normal NEC code - 16 bits */ | 732 | keycode = RC_SCANCODE_NEC(poll_reply->system, |
| 726 | keycode = poll_reply->system << 8 | poll_reply->data; | 733 | poll_reply->data); |
| 727 | } | 734 | } |
| 728 | 735 | ||
| 729 | break; | 736 | break; |
| 730 | default: | 737 | default: |
| 731 | deb_data("RC5 protocol\n"); | 738 | deb_data("RC5 protocol\n"); |
| 732 | /* RC5 Protocol */ | 739 | protocol = RC_TYPE_RC5; |
| 733 | toggle = poll_reply->report_id; | 740 | toggle = poll_reply->report_id; |
| 734 | keycode = poll_reply->system << 8 | poll_reply->data; | 741 | keycode = RC_SCANCODE_RC5(poll_reply->system, poll_reply->data); |
| 735 | 742 | ||
| 736 | break; | 743 | break; |
| 737 | } | 744 | } |
| 738 | 745 | ||
| 739 | if ((poll_reply->data + poll_reply->not_data) != 0xff) { | 746 | if ((poll_reply->data + poll_reply->not_data) != 0xff) { |
| 740 | /* Key failed integrity check */ | 747 | /* Key failed integrity check */ |
| 741 | err("key failed integrity check: %04x %02x %02x", | 748 | err("key failed integrity check: %02x %02x %02x %02x", |
| 742 | poll_reply->system, | 749 | poll_reply->system, poll_reply->not_system, |
| 743 | poll_reply->data, poll_reply->not_data); | 750 | poll_reply->data, poll_reply->not_data); |
| 744 | goto resubmit; | 751 | goto resubmit; |
| 745 | } | 752 | } |
| 746 | 753 | ||
| 747 | rc_keydown(d->rc_dev, keycode, toggle); | 754 | rc_keydown(d->rc_dev, protocol, keycode, toggle); |
| 748 | 755 | ||
| 749 | resubmit: | 756 | resubmit: |
| 750 | /* Clean the buffer before we requeue */ | 757 | /* Clean the buffer before we requeue */ |
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 10e0db8d1850..ce47d3f1c850 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c | |||
| @@ -32,6 +32,8 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif | |||
| 32 | struct dib0700_adapter_state { | 32 | struct dib0700_adapter_state { |
| 33 | int (*set_param_save) (struct dvb_frontend *); | 33 | int (*set_param_save) (struct dvb_frontend *); |
| 34 | const struct firmware *frontend_firmware; | 34 | const struct firmware *frontend_firmware; |
| 35 | struct dib7000p_ops dib7000p_ops; | ||
| 36 | struct dib8000_ops dib8000_ops; | ||
| 35 | }; | 37 | }; |
| 36 | 38 | ||
| 37 | /* Hauppauge Nova-T 500 (aka Bristol) | 39 | /* Hauppauge Nova-T 500 (aka Bristol) |
| @@ -262,6 +264,11 @@ static struct mt2266_config stk7700d_mt2266_config[2] = { | |||
| 262 | 264 | ||
| 263 | static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) | 265 | static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) |
| 264 | { | 266 | { |
| 267 | struct dib0700_adapter_state *state = adap->priv; | ||
| 268 | |||
| 269 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 270 | return -ENODEV; | ||
| 271 | |||
| 265 | if (adap->id == 0) { | 272 | if (adap->id == 0) { |
| 266 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 273 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| 267 | msleep(10); | 274 | msleep(10); |
| @@ -272,16 +279,16 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 272 | msleep(10); | 279 | msleep(10); |
| 273 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | 280 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); |
| 274 | msleep(10); | 281 | msleep(10); |
| 275 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 282 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, |
| 276 | stk7700d_dib7000p_mt2266_config) | 283 | stk7700d_dib7000p_mt2266_config) |
| 277 | != 0) { | 284 | != 0) { |
| 278 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | 285 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); |
| 286 | dvb_detach(&state->dib7000p_ops); | ||
| 279 | return -ENODEV; | 287 | return -ENODEV; |
| 280 | } | 288 | } |
| 281 | } | 289 | } |
| 282 | 290 | ||
| 283 | adap->fe_adap[0].fe = | 291 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, |
| 284 | dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, | ||
| 285 | 0x80 + (adap->id << 1), | 292 | 0x80 + (adap->id << 1), |
| 286 | &stk7700d_dib7000p_mt2266_config[adap->id]); | 293 | &stk7700d_dib7000p_mt2266_config[adap->id]); |
| 287 | 294 | ||
| @@ -290,6 +297,11 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 290 | 297 | ||
| 291 | static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) | 298 | static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) |
| 292 | { | 299 | { |
| 300 | struct dib0700_adapter_state *state = adap->priv; | ||
| 301 | |||
| 302 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 303 | return -ENODEV; | ||
| 304 | |||
| 293 | if (adap->id == 0) { | 305 | if (adap->id == 0) { |
| 294 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 306 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| 295 | msleep(10); | 307 | msleep(10); |
| @@ -301,16 +313,16 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 301 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); | 313 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); |
| 302 | msleep(10); | 314 | msleep(10); |
| 303 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 315 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 304 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, | 316 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18, |
| 305 | stk7700d_dib7000p_mt2266_config) | 317 | stk7700d_dib7000p_mt2266_config) |
| 306 | != 0) { | 318 | != 0) { |
| 307 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | 319 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); |
| 320 | dvb_detach(&state->dib7000p_ops); | ||
| 308 | return -ENODEV; | 321 | return -ENODEV; |
| 309 | } | 322 | } |
| 310 | } | 323 | } |
| 311 | 324 | ||
| 312 | adap->fe_adap[0].fe = | 325 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, |
| 313 | dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, | ||
| 314 | 0x80 + (adap->id << 1), | 326 | 0x80 + (adap->id << 1), |
| 315 | &stk7700d_dib7000p_mt2266_config[adap->id]); | 327 | &stk7700d_dib7000p_mt2266_config[adap->id]); |
| 316 | 328 | ||
| @@ -320,7 +332,10 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 320 | static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap) | 332 | static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap) |
| 321 | { | 333 | { |
| 322 | struct i2c_adapter *tun_i2c; | 334 | struct i2c_adapter *tun_i2c; |
| 323 | tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); | 335 | struct dib0700_adapter_state *state = adap->priv; |
| 336 | |||
| 337 | tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, | ||
| 338 | DIBX000_I2C_INTERFACE_TUNER, 1); | ||
| 324 | return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c, | 339 | return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c, |
| 325 | &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0; | 340 | &stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0; |
| 326 | } | 341 | } |
| @@ -397,12 +412,14 @@ static int stk7700ph_xc3028_callback(void *ptr, int component, | |||
| 397 | int command, int arg) | 412 | int command, int arg) |
| 398 | { | 413 | { |
| 399 | struct dvb_usb_adapter *adap = ptr; | 414 | struct dvb_usb_adapter *adap = ptr; |
| 415 | struct dib0700_adapter_state *state = adap->priv; | ||
| 400 | 416 | ||
| 401 | switch (command) { | 417 | switch (command) { |
| 402 | case XC2028_TUNER_RESET: | 418 | case XC2028_TUNER_RESET: |
| 403 | /* Send the tuner in then out of reset */ | 419 | /* Send the tuner in then out of reset */ |
| 404 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10); | 420 | state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0); |
| 405 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 421 | msleep(10); |
| 422 | state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | ||
| 406 | break; | 423 | break; |
| 407 | case XC2028_RESET_CLK: | 424 | case XC2028_RESET_CLK: |
| 408 | break; | 425 | break; |
| @@ -428,12 +445,16 @@ static struct xc2028_config stk7700ph_xc3028_config = { | |||
| 428 | static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) | 445 | static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) |
| 429 | { | 446 | { |
| 430 | struct usb_device_descriptor *desc = &adap->dev->udev->descriptor; | 447 | struct usb_device_descriptor *desc = &adap->dev->udev->descriptor; |
| 448 | struct dib0700_adapter_state *state = adap->priv; | ||
| 449 | |||
| 450 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 451 | return -ENODEV; | ||
| 431 | 452 | ||
| 432 | if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) && | 453 | if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) && |
| 433 | desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX)) | 454 | desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX)) |
| 434 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | 455 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); |
| 435 | else | 456 | else |
| 436 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 457 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| 437 | msleep(20); | 458 | msleep(20); |
| 438 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | 459 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); |
| 439 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); | 460 | dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); |
| @@ -445,14 +466,15 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 445 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 466 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 446 | msleep(10); | 467 | msleep(10); |
| 447 | 468 | ||
| 448 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 469 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, |
| 449 | &stk7700ph_dib7700_xc3028_config) != 0) { | 470 | &stk7700ph_dib7700_xc3028_config) != 0) { |
| 450 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | 471 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", |
| 451 | __func__); | 472 | __func__); |
| 473 | dvb_detach(&state->dib7000p_ops); | ||
| 452 | return -ENODEV; | 474 | return -ENODEV; |
| 453 | } | 475 | } |
| 454 | 476 | ||
| 455 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | 477 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, |
| 456 | &stk7700ph_dib7700_xc3028_config); | 478 | &stk7700ph_dib7700_xc3028_config); |
| 457 | 479 | ||
| 458 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 480 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| @@ -461,8 +483,9 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 461 | static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) | 483 | static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) |
| 462 | { | 484 | { |
| 463 | struct i2c_adapter *tun_i2c; | 485 | struct i2c_adapter *tun_i2c; |
| 486 | struct dib0700_adapter_state *state = adap->priv; | ||
| 464 | 487 | ||
| 465 | tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, | 488 | tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, |
| 466 | DIBX000_I2C_INTERFACE_TUNER, 1); | 489 | DIBX000_I2C_INTERFACE_TUNER, 1); |
| 467 | 490 | ||
| 468 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; | 491 | stk7700ph_xc3028_config.i2c_adap = tun_i2c; |
| @@ -489,7 +512,8 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | |||
| 489 | static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) | 512 | static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) |
| 490 | { | 513 | { |
| 491 | u8 key[4]; | 514 | u8 key[4]; |
| 492 | u32 keycode; | 515 | enum rc_type protocol; |
| 516 | u32 scancode; | ||
| 493 | u8 toggle; | 517 | u8 toggle; |
| 494 | int i; | 518 | int i; |
| 495 | struct dib0700_state *st = d->priv; | 519 | struct dib0700_state *st = d->priv; |
| @@ -516,28 +540,29 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d) | |||
| 516 | 540 | ||
| 517 | dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */ | 541 | dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */ |
| 518 | 542 | ||
| 519 | d->last_event = 0; | ||
| 520 | switch (d->props.rc.core.protocol) { | 543 | switch (d->props.rc.core.protocol) { |
| 521 | case RC_BIT_NEC: | 544 | case RC_BIT_NEC: |
| 522 | /* NEC protocol sends repeat code as 0 0 0 FF */ | 545 | /* NEC protocol sends repeat code as 0 0 0 FF */ |
| 523 | if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && | 546 | if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && |
| 524 | (key[3] == 0xff)) | 547 | (key[3] == 0xff)) { |
| 525 | keycode = d->last_event; | 548 | rc_repeat(d->rc_dev); |
| 526 | else { | 549 | return 0; |
| 527 | keycode = key[3-2] << 8 | key[3-3]; | ||
| 528 | d->last_event = keycode; | ||
| 529 | } | 550 | } |
| 530 | 551 | ||
| 531 | rc_keydown(d->rc_dev, keycode, 0); | 552 | protocol = RC_TYPE_NEC; |
| 553 | scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]); | ||
| 554 | toggle = 0; | ||
| 532 | break; | 555 | break; |
| 556 | |||
| 533 | default: | 557 | default: |
| 534 | /* RC-5 protocol changes toggle bit on new keypress */ | 558 | /* RC-5 protocol changes toggle bit on new keypress */ |
| 535 | keycode = key[3-2] << 8 | key[3-3]; | 559 | protocol = RC_TYPE_RC5; |
| 560 | scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]); | ||
| 536 | toggle = key[3-1]; | 561 | toggle = key[3-1]; |
| 537 | rc_keydown(d->rc_dev, keycode, toggle); | ||
| 538 | |||
| 539 | break; | 562 | break; |
| 540 | } | 563 | } |
| 564 | |||
| 565 | rc_keydown(d->rc_dev, protocol, scancode, toggle); | ||
| 541 | return 0; | 566 | return 0; |
| 542 | } | 567 | } |
| 543 | 568 | ||
| @@ -673,6 +698,11 @@ static struct dib7000p_config stk7700p_dib7000p_config = { | |||
| 673 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) | 698 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) |
| 674 | { | 699 | { |
| 675 | struct dib0700_state *st = adap->dev->priv; | 700 | struct dib0700_state *st = adap->dev->priv; |
| 701 | struct dib0700_adapter_state *state = adap->priv; | ||
| 702 | |||
| 703 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 704 | return -ENODEV; | ||
| 705 | |||
| 676 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ | 706 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ |
| 677 | 707 | ||
| 678 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); | 708 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); |
| @@ -689,11 +719,13 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 689 | 719 | ||
| 690 | st->mt2060_if1[0] = 1220; | 720 | st->mt2060_if1[0] = 1220; |
| 691 | 721 | ||
| 692 | if (dib7000pc_detection(&adap->dev->i2c_adap)) { | 722 | if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap)) { |
| 693 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); | 723 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config); |
| 694 | st->is_dib7000pc = 1; | 724 | st->is_dib7000pc = 1; |
| 695 | } else | 725 | } else { |
| 726 | memset(&state->dib7000p_ops, 0, sizeof(state->dib7000p_ops)); | ||
| 696 | adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); | 727 | adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config); |
| 728 | } | ||
| 697 | 729 | ||
| 698 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 730 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 699 | } | 731 | } |
| @@ -707,14 +739,16 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 707 | struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap; | 739 | struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap; |
| 708 | struct dib0700_state *st = adap->dev->priv; | 740 | struct dib0700_state *st = adap->dev->priv; |
| 709 | struct i2c_adapter *tun_i2c; | 741 | struct i2c_adapter *tun_i2c; |
| 742 | struct dib0700_adapter_state *state = adap->priv; | ||
| 710 | s8 a; | 743 | s8 a; |
| 711 | int if1=1220; | 744 | int if1=1220; |
| 745 | |||
| 712 | if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) && | 746 | if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) && |
| 713 | adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) { | 747 | adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) { |
| 714 | if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a; | 748 | if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a; |
| 715 | } | 749 | } |
| 716 | if (st->is_dib7000pc) | 750 | if (st->is_dib7000pc) |
| 717 | tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); | 751 | tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); |
| 718 | else | 752 | else |
| 719 | tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); | 753 | tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); |
| 720 | 754 | ||
| @@ -767,14 +801,20 @@ static struct dibx000_agc_config dib7070_agc_config = { | |||
| 767 | 801 | ||
| 768 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) | 802 | static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) |
| 769 | { | 803 | { |
| 804 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 805 | struct dib0700_adapter_state *state = adap->priv; | ||
| 806 | |||
| 770 | deb_info("reset: %d", onoff); | 807 | deb_info("reset: %d", onoff); |
| 771 | return dib7000p_set_gpio(fe, 8, 0, !onoff); | 808 | return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff); |
| 772 | } | 809 | } |
| 773 | 810 | ||
| 774 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) | 811 | static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) |
| 775 | { | 812 | { |
| 813 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 814 | struct dib0700_adapter_state *state = adap->priv; | ||
| 815 | |||
| 776 | deb_info("sleep: %d", onoff); | 816 | deb_info("sleep: %d", onoff); |
| 777 | return dib7000p_set_gpio(fe, 9, 0, onoff); | 817 | return state->dib7000p_ops.set_gpio(fe, 9, 0, onoff); |
| 778 | } | 818 | } |
| 779 | 819 | ||
| 780 | static struct dib0070_config dib7070p_dib0070_config[2] = { | 820 | static struct dib0070_config dib7070p_dib0070_config[2] = { |
| @@ -818,7 +858,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe) | |||
| 818 | default: offset = 550; break; | 858 | default: offset = 550; break; |
| 819 | } | 859 | } |
| 820 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); | 860 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); |
| 821 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | 861 | state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); |
| 822 | return state->set_param_save(fe); | 862 | return state->set_param_save(fe); |
| 823 | } | 863 | } |
| 824 | 864 | ||
| @@ -832,39 +872,39 @@ static int dib7770_set_param_override(struct dvb_frontend *fe) | |||
| 832 | u8 band = BAND_OF_FREQUENCY(p->frequency/1000); | 872 | u8 band = BAND_OF_FREQUENCY(p->frequency/1000); |
| 833 | switch (band) { | 873 | switch (band) { |
| 834 | case BAND_VHF: | 874 | case BAND_VHF: |
| 835 | dib7000p_set_gpio(fe, 0, 0, 1); | 875 | state->dib7000p_ops.set_gpio(fe, 0, 0, 1); |
| 836 | offset = 850; | 876 | offset = 850; |
| 837 | break; | 877 | break; |
| 838 | case BAND_UHF: | 878 | case BAND_UHF: |
| 839 | default: | 879 | default: |
| 840 | dib7000p_set_gpio(fe, 0, 0, 0); | 880 | state->dib7000p_ops.set_gpio(fe, 0, 0, 0); |
| 841 | offset = 250; | 881 | offset = 250; |
| 842 | break; | 882 | break; |
| 843 | } | 883 | } |
| 844 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); | 884 | deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe)); |
| 845 | dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); | 885 | state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe)); |
| 846 | return state->set_param_save(fe); | 886 | return state->set_param_save(fe); |
| 847 | } | 887 | } |
| 848 | 888 | ||
| 849 | static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap) | 889 | static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap) |
| 850 | { | 890 | { |
| 851 | struct dib0700_adapter_state *st = adap->priv; | 891 | struct dib0700_adapter_state *st = adap->priv; |
| 852 | struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, | 892 | struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, |
| 853 | DIBX000_I2C_INTERFACE_TUNER, 1); | 893 | DIBX000_I2C_INTERFACE_TUNER, 1); |
| 854 | 894 | ||
| 855 | if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, | 895 | if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, |
| 856 | &dib7770p_dib0070_config) == NULL) | 896 | &dib7770p_dib0070_config) == NULL) |
| 857 | return -ENODEV; | 897 | return -ENODEV; |
| 858 | 898 | ||
| 859 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; | 899 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; |
| 860 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override; | 900 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override; |
| 861 | return 0; | 901 | return 0; |
| 862 | } | 902 | } |
| 863 | 903 | ||
| 864 | static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) | 904 | static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) |
| 865 | { | 905 | { |
| 866 | struct dib0700_adapter_state *st = adap->priv; | 906 | struct dib0700_adapter_state *st = adap->priv; |
| 867 | struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); | 907 | struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); |
| 868 | 908 | ||
| 869 | if (adap->id == 0) { | 909 | if (adap->id == 0) { |
| 870 | if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL) | 910 | if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL) |
| @@ -882,28 +922,33 @@ static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 882 | static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index, | 922 | static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index, |
| 883 | u16 pid, int onoff) | 923 | u16 pid, int onoff) |
| 884 | { | 924 | { |
| 925 | struct dib0700_adapter_state *state = adapter->priv; | ||
| 885 | struct dib0700_state *st = adapter->dev->priv; | 926 | struct dib0700_state *st = adapter->dev->priv; |
| 927 | |||
| 886 | if (st->is_dib7000pc) | 928 | if (st->is_dib7000pc) |
| 887 | return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); | 929 | return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); |
| 888 | return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); | 930 | return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); |
| 889 | } | 931 | } |
| 890 | 932 | ||
| 891 | static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | 933 | static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) |
| 892 | { | 934 | { |
| 893 | struct dib0700_state *st = adapter->dev->priv; | 935 | struct dib0700_state *st = adapter->dev->priv; |
| 936 | struct dib0700_adapter_state *state = adapter->priv; | ||
| 894 | if (st->is_dib7000pc) | 937 | if (st->is_dib7000pc) |
| 895 | return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); | 938 | return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); |
| 896 | return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); | 939 | return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); |
| 897 | } | 940 | } |
| 898 | 941 | ||
| 899 | static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) | 942 | static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff) |
| 900 | { | 943 | { |
| 901 | return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); | 944 | struct dib0700_adapter_state *state = adapter->priv; |
| 945 | return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); | ||
| 902 | } | 946 | } |
| 903 | 947 | ||
| 904 | static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) | 948 | static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff) |
| 905 | { | 949 | { |
| 906 | return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); | 950 | struct dib0700_adapter_state *state = adapter->priv; |
| 951 | return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); | ||
| 907 | } | 952 | } |
| 908 | 953 | ||
| 909 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { | 954 | static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = { |
| @@ -936,6 +981,11 @@ static struct dib7000p_config dib7070p_dib7000p_config = { | |||
| 936 | static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) | 981 | static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) |
| 937 | { | 982 | { |
| 938 | struct usb_device_descriptor *p = &adap->dev->udev->descriptor; | 983 | struct usb_device_descriptor *p = &adap->dev->udev->descriptor; |
| 984 | struct dib0700_adapter_state *state = adap->priv; | ||
| 985 | |||
| 986 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 987 | return -ENODEV; | ||
| 988 | |||
| 939 | if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && | 989 | if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && |
| 940 | p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) | 990 | p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) |
| 941 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | 991 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); |
| @@ -954,14 +1004,15 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 954 | msleep(10); | 1004 | msleep(10); |
| 955 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1005 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 956 | 1006 | ||
| 957 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 1007 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, |
| 958 | &dib7070p_dib7000p_config) != 0) { | 1008 | &dib7070p_dib7000p_config) != 0) { |
| 959 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | 1009 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", |
| 960 | __func__); | 1010 | __func__); |
| 1011 | dvb_detach(&state->dib7000p_ops); | ||
| 961 | return -ENODEV; | 1012 | return -ENODEV; |
| 962 | } | 1013 | } |
| 963 | 1014 | ||
| 964 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | 1015 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, |
| 965 | &dib7070p_dib7000p_config); | 1016 | &dib7070p_dib7000p_config); |
| 966 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 1017 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 967 | } | 1018 | } |
| @@ -988,6 +1039,11 @@ static struct dib7000p_config dib7770p_dib7000p_config = { | |||
| 988 | static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) | 1039 | static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) |
| 989 | { | 1040 | { |
| 990 | struct usb_device_descriptor *p = &adap->dev->udev->descriptor; | 1041 | struct usb_device_descriptor *p = &adap->dev->udev->descriptor; |
| 1042 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1043 | |||
| 1044 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 1045 | return -ENODEV; | ||
| 1046 | |||
| 991 | if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && | 1047 | if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && |
| 992 | p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) | 1048 | p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) |
| 993 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | 1049 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); |
| @@ -1006,14 +1062,15 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1006 | msleep(10); | 1062 | msleep(10); |
| 1007 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1063 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 1008 | 1064 | ||
| 1009 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 1065 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, |
| 1010 | &dib7770p_dib7000p_config) != 0) { | 1066 | &dib7770p_dib7000p_config) != 0) { |
| 1011 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | 1067 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", |
| 1012 | __func__); | 1068 | __func__); |
| 1069 | dvb_detach(&state->dib7000p_ops); | ||
| 1013 | return -ENODEV; | 1070 | return -ENODEV; |
| 1014 | } | 1071 | } |
| 1015 | 1072 | ||
| 1016 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, | 1073 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, |
| 1017 | &dib7770p_dib7000p_config); | 1074 | &dib7770p_dib7000p_config); |
| 1018 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 1075 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 1019 | } | 1076 | } |
| @@ -1161,12 +1218,18 @@ static struct dib8000_config dib807x_dib8000_config[2] = { | |||
| 1161 | 1218 | ||
| 1162 | static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff) | 1219 | static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff) |
| 1163 | { | 1220 | { |
| 1164 | return dib8000_set_gpio(fe, 5, 0, !onoff); | 1221 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
| 1222 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1223 | |||
| 1224 | return state->dib8000_ops.set_gpio(fe, 5, 0, !onoff); | ||
| 1165 | } | 1225 | } |
| 1166 | 1226 | ||
| 1167 | static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff) | 1227 | static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff) |
| 1168 | { | 1228 | { |
| 1169 | return dib8000_set_gpio(fe, 0, 0, onoff); | 1229 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
| 1230 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1231 | |||
| 1232 | return state->dib8000_ops.set_gpio(fe, 0, 0, onoff); | ||
| 1170 | } | 1233 | } |
| 1171 | 1234 | ||
| 1172 | static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = { | 1235 | static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = { |
| @@ -1223,7 +1286,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe) | |||
| 1223 | offset += 250; break; | 1286 | offset += 250; break; |
| 1224 | } | 1287 | } |
| 1225 | deb_info("WBD for DiB8000: %d\n", offset); | 1288 | deb_info("WBD for DiB8000: %d\n", offset); |
| 1226 | dib8000_set_wbd_ref(fe, offset); | 1289 | state->dib8000_ops.set_wbd_ref(fe, offset); |
| 1227 | 1290 | ||
| 1228 | return state->set_param_save(fe); | 1291 | return state->set_param_save(fe); |
| 1229 | } | 1292 | } |
| @@ -1231,7 +1294,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe) | |||
| 1231 | static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) | 1294 | static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) |
| 1232 | { | 1295 | { |
| 1233 | struct dib0700_adapter_state *st = adap->priv; | 1296 | struct dib0700_adapter_state *st = adap->priv; |
| 1234 | struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, | 1297 | struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, |
| 1235 | DIBX000_I2C_INTERFACE_TUNER, 1); | 1298 | DIBX000_I2C_INTERFACE_TUNER, 1); |
| 1236 | 1299 | ||
| 1237 | if (adap->id == 0) { | 1300 | if (adap->id == 0) { |
| @@ -1252,18 +1315,27 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 1252 | static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, | 1315 | static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index, |
| 1253 | u16 pid, int onoff) | 1316 | u16 pid, int onoff) |
| 1254 | { | 1317 | { |
| 1255 | return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); | 1318 | struct dib0700_adapter_state *state = adapter->priv; |
| 1319 | |||
| 1320 | return state->dib8000_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff); | ||
| 1256 | } | 1321 | } |
| 1257 | 1322 | ||
| 1258 | static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, | 1323 | static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter, |
| 1259 | int onoff) | 1324 | int onoff) |
| 1260 | { | 1325 | { |
| 1261 | return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); | 1326 | struct dib0700_adapter_state *state = adapter->priv; |
| 1327 | |||
| 1328 | return state->dib8000_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff); | ||
| 1262 | } | 1329 | } |
| 1263 | 1330 | ||
| 1264 | /* STK807x */ | 1331 | /* STK807x */ |
| 1265 | static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) | 1332 | static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) |
| 1266 | { | 1333 | { |
| 1334 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1335 | |||
| 1336 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) | ||
| 1337 | return -ENODEV; | ||
| 1338 | |||
| 1267 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 1339 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| 1268 | msleep(10); | 1340 | msleep(10); |
| 1269 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | 1341 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); |
| @@ -1279,10 +1351,10 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1279 | msleep(10); | 1351 | msleep(10); |
| 1280 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1352 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 1281 | 1353 | ||
| 1282 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, | 1354 | state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, |
| 1283 | 0x80, 0); | 1355 | 0x80, 0); |
| 1284 | 1356 | ||
| 1285 | adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | 1357 | adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, |
| 1286 | &dib807x_dib8000_config[0]); | 1358 | &dib807x_dib8000_config[0]); |
| 1287 | 1359 | ||
| 1288 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 1360 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| @@ -1291,6 +1363,11 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1291 | /* STK807xPVR */ | 1363 | /* STK807xPVR */ |
| 1292 | static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | 1364 | static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) |
| 1293 | { | 1365 | { |
| 1366 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1367 | |||
| 1368 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) | ||
| 1369 | return -ENODEV; | ||
| 1370 | |||
| 1294 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | 1371 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); |
| 1295 | msleep(30); | 1372 | msleep(30); |
| 1296 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 1373 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| @@ -1309,9 +1386,9 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | |||
| 1309 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1386 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 1310 | 1387 | ||
| 1311 | /* initialize IC 0 */ | 1388 | /* initialize IC 0 */ |
| 1312 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0); | 1389 | state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0); |
| 1313 | 1390 | ||
| 1314 | adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, | 1391 | adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, |
| 1315 | &dib807x_dib8000_config[0]); | 1392 | &dib807x_dib8000_config[0]); |
| 1316 | 1393 | ||
| 1317 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 1394 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| @@ -1319,10 +1396,15 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap) | |||
| 1319 | 1396 | ||
| 1320 | static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) | 1397 | static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) |
| 1321 | { | 1398 | { |
| 1399 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1400 | |||
| 1401 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) | ||
| 1402 | return -ENODEV; | ||
| 1403 | |||
| 1322 | /* initialize IC 1 */ | 1404 | /* initialize IC 1 */ |
| 1323 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0); | 1405 | state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0); |
| 1324 | 1406 | ||
| 1325 | adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, | 1407 | adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, |
| 1326 | &dib807x_dib8000_config[1]); | 1408 | &dib807x_dib8000_config[1]); |
| 1327 | 1409 | ||
| 1328 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 1410 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| @@ -1331,104 +1413,121 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap) | |||
| 1331 | /* STK8096GP */ | 1413 | /* STK8096GP */ |
| 1332 | static struct dibx000_agc_config dib8090_agc_config[2] = { | 1414 | static struct dibx000_agc_config dib8090_agc_config[2] = { |
| 1333 | { | 1415 | { |
| 1334 | BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, | 1416 | .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND, |
| 1335 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, | 1417 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, |
| 1336 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | 1418 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, |
| 1337 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | 1419 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ |
| 1338 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | 1420 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
| 1339 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | 1421 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), |
| 1340 | 1422 | ||
| 1341 | 787, | 1423 | .inv_gain = 787, |
| 1342 | 10, | 1424 | .time_stabiliz = 10, |
| 1343 | |||
| 1344 | 0, | ||
| 1345 | 118, | ||
| 1346 | |||
| 1347 | 0, | ||
| 1348 | 3530, | ||
| 1349 | 1, | ||
| 1350 | 5, | ||
| 1351 | 1425 | ||
| 1352 | 65535, | 1426 | .alpha_level = 0, |
| 1353 | 0, | 1427 | .thlock = 118, |
| 1354 | 1428 | ||
| 1355 | 65535, | 1429 | .wbd_inv = 0, |
| 1356 | 0, | 1430 | .wbd_ref = 3530, |
| 1431 | .wbd_sel = 1, | ||
| 1432 | .wbd_alpha = 5, | ||
| 1357 | 1433 | ||
| 1358 | 0, | 1434 | .agc1_max = 65535, |
| 1359 | 32, | 1435 | .agc1_min = 0, |
| 1360 | 114, | ||
| 1361 | 143, | ||
| 1362 | 144, | ||
| 1363 | 114, | ||
| 1364 | 227, | ||
| 1365 | 116, | ||
| 1366 | 117, | ||
| 1367 | 1436 | ||
| 1368 | 28, | 1437 | .agc2_max = 65535, |
| 1369 | 26, | 1438 | .agc2_min = 0, |
| 1370 | 31, | ||
| 1371 | 51, | ||
| 1372 | 1439 | ||
| 1373 | 0, | 1440 | .agc1_pt1 = 0, |
| 1441 | .agc1_pt2 = 32, | ||
| 1442 | .agc1_pt3 = 114, | ||
| 1443 | .agc1_slope1 = 143, | ||
| 1444 | .agc1_slope2 = 144, | ||
| 1445 | .agc2_pt1 = 114, | ||
| 1446 | .agc2_pt2 = 227, | ||
| 1447 | .agc2_slope1 = 116, | ||
| 1448 | .agc2_slope2 = 117, | ||
| 1449 | |||
| 1450 | .alpha_mant = 28, | ||
| 1451 | .alpha_exp = 26, | ||
| 1452 | .beta_mant = 31, | ||
| 1453 | .beta_exp = 51, | ||
| 1454 | |||
| 1455 | .perform_agc_softsplit = 0, | ||
| 1374 | }, | 1456 | }, |
| 1375 | { | 1457 | { |
| 1376 | BAND_CBAND, | 1458 | .band_caps = BAND_CBAND, |
| 1377 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, | 1459 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, |
| 1378 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, | 1460 | * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0, |
| 1379 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ | 1461 | * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */ |
| 1380 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | 1462 | .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
| 1381 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), | 1463 | | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0), |
| 1382 | 1464 | ||
| 1383 | 787, | 1465 | .inv_gain = 787, |
| 1384 | 10, | 1466 | .time_stabiliz = 10, |
| 1385 | 1467 | ||
| 1386 | 0, | 1468 | .alpha_level = 0, |
| 1387 | 118, | 1469 | .thlock = 118, |
| 1388 | 1470 | ||
| 1389 | 0, | 1471 | .wbd_inv = 0, |
| 1390 | 3530, | 1472 | .wbd_ref = 3530, |
| 1391 | 1, | 1473 | .wbd_sel = 1, |
| 1392 | 5, | 1474 | .wbd_alpha = 5, |
| 1393 | 1475 | ||
| 1394 | 0, | 1476 | .agc1_max = 0, |
| 1395 | 0, | 1477 | .agc1_min = 0, |
| 1396 | 1478 | ||
| 1397 | 65535, | 1479 | .agc2_max = 65535, |
| 1398 | 0, | 1480 | .agc2_min = 0, |
| 1399 | |||
| 1400 | 0, | ||
| 1401 | 32, | ||
| 1402 | 114, | ||
| 1403 | 143, | ||
| 1404 | 144, | ||
| 1405 | 114, | ||
| 1406 | 227, | ||
| 1407 | 116, | ||
| 1408 | 117, | ||
| 1409 | |||
| 1410 | 28, | ||
| 1411 | 26, | ||
| 1412 | 31, | ||
| 1413 | 51, | ||
| 1414 | 1481 | ||
| 1415 | 0, | 1482 | .agc1_pt1 = 0, |
| 1483 | .agc1_pt2 = 32, | ||
| 1484 | .agc1_pt3 = 114, | ||
| 1485 | .agc1_slope1 = 143, | ||
| 1486 | .agc1_slope2 = 144, | ||
| 1487 | .agc2_pt1 = 114, | ||
| 1488 | .agc2_pt2 = 227, | ||
| 1489 | .agc2_slope1 = 116, | ||
| 1490 | .agc2_slope2 = 117, | ||
| 1491 | |||
| 1492 | .alpha_mant = 28, | ||
| 1493 | .alpha_exp = 26, | ||
| 1494 | .beta_mant = 31, | ||
| 1495 | .beta_exp = 51, | ||
| 1496 | |||
| 1497 | .perform_agc_softsplit = 0, | ||
| 1416 | } | 1498 | } |
| 1417 | }; | 1499 | }; |
| 1418 | 1500 | ||
| 1419 | static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { | 1501 | static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = { |
| 1420 | 54000, 13500, | 1502 | .internal = 54000, |
| 1421 | 1, 18, 3, 1, 0, | 1503 | .sampling = 13500, |
| 1422 | 0, 0, 1, 1, 2, | 1504 | |
| 1423 | (3 << 14) | (1 << 12) | (599 << 0), | 1505 | .pll_prediv = 1, |
| 1424 | (0 << 25) | 0, | 1506 | .pll_ratio = 18, |
| 1425 | 20199727, | 1507 | .pll_range = 3, |
| 1426 | 12000000, | 1508 | .pll_reset = 1, |
| 1509 | .pll_bypass = 0, | ||
| 1510 | |||
| 1511 | .enable_refdiv = 0, | ||
| 1512 | .bypclk_div = 0, | ||
| 1513 | .IO_CLK_en_core = 1, | ||
| 1514 | .ADClkSrc = 1, | ||
| 1515 | .modulo = 2, | ||
| 1516 | |||
| 1517 | .sad_cfg = (3 << 14) | (1 << 12) | (599 << 0), | ||
| 1518 | |||
| 1519 | .ifreq = (0 << 25) | 0, | ||
| 1520 | .timf = 20199727, | ||
| 1521 | |||
| 1522 | .xtal_hz = 12000000, | ||
| 1427 | }; | 1523 | }; |
| 1428 | 1524 | ||
| 1429 | static int dib8090_get_adc_power(struct dvb_frontend *fe) | 1525 | static int dib8090_get_adc_power(struct dvb_frontend *fe) |
| 1430 | { | 1526 | { |
| 1431 | return dib8000_get_adc_power(fe, 1); | 1527 | struct dvb_usb_adapter *adap = fe->dvb->priv; |
| 1528 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1529 | |||
| 1530 | return state->dib8000_ops.get_adc_power(fe, 1); | ||
| 1432 | } | 1531 | } |
| 1433 | 1532 | ||
| 1434 | static void dib8090_agc_control(struct dvb_frontend *fe, u8 restart) | 1533 | static void dib8090_agc_control(struct dvb_frontend *fe, u8 restart) |
| @@ -1551,10 +1650,10 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) | |||
| 1551 | default: | 1650 | default: |
| 1552 | deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency); | 1651 | deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency); |
| 1553 | case BAND_VHF: | 1652 | case BAND_VHF: |
| 1554 | dib8000_set_gpio(fe, 3, 0, 1); | 1653 | state->dib8000_ops.set_gpio(fe, 3, 0, 1); |
| 1555 | break; | 1654 | break; |
| 1556 | case BAND_UHF: | 1655 | case BAND_UHF: |
| 1557 | dib8000_set_gpio(fe, 3, 0, 0); | 1656 | state->dib8000_ops.set_gpio(fe, 3, 0, 0); |
| 1558 | break; | 1657 | break; |
| 1559 | } | 1658 | } |
| 1560 | 1659 | ||
| @@ -1568,7 +1667,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) | |||
| 1568 | } | 1667 | } |
| 1569 | 1668 | ||
| 1570 | /** Update PLL if needed ratio **/ | 1669 | /** Update PLL if needed ratio **/ |
| 1571 | dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0); | 1670 | state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0); |
| 1572 | 1671 | ||
| 1573 | /** Get optimize PLL ratio to remove spurious **/ | 1672 | /** Get optimize PLL ratio to remove spurious **/ |
| 1574 | pll_ratio = dib8090_compute_pll_parameters(fe); | 1673 | pll_ratio = dib8090_compute_pll_parameters(fe); |
| @@ -1582,14 +1681,14 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) | |||
| 1582 | timf = 18179756; | 1681 | timf = 18179756; |
| 1583 | 1682 | ||
| 1584 | /** Update ratio **/ | 1683 | /** Update ratio **/ |
| 1585 | dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio); | 1684 | state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio); |
| 1586 | 1685 | ||
| 1587 | dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, timf); | 1686 | state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, timf); |
| 1588 | 1687 | ||
| 1589 | if (band != BAND_CBAND) { | 1688 | if (band != BAND_CBAND) { |
| 1590 | /* dib0090_get_wbd_target is returning any possible temperature compensated wbd-target */ | 1689 | /* dib0090_get_wbd_target is returning any possible temperature compensated wbd-target */ |
| 1591 | target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2; | 1690 | target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2; |
| 1592 | dib8000_set_wbd_ref(fe, target); | 1691 | state->dib8000_ops.set_wbd_ref(fe, target); |
| 1593 | } | 1692 | } |
| 1594 | 1693 | ||
| 1595 | if (band == BAND_CBAND) { | 1694 | if (band == BAND_CBAND) { |
| @@ -1601,18 +1700,18 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) | |||
| 1601 | msleep(ret); | 1700 | msleep(ret); |
| 1602 | tune_state = dib0090_get_tune_state(fe); | 1701 | tune_state = dib0090_get_tune_state(fe); |
| 1603 | if (tune_state == CT_AGC_STEP_0) | 1702 | if (tune_state == CT_AGC_STEP_0) |
| 1604 | dib8000_set_gpio(fe, 6, 0, 1); | 1703 | state->dib8000_ops.set_gpio(fe, 6, 0, 1); |
| 1605 | else if (tune_state == CT_AGC_STEP_1) { | 1704 | else if (tune_state == CT_AGC_STEP_1) { |
| 1606 | dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); | 1705 | dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, <gain); |
| 1607 | if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */ | 1706 | if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */ |
| 1608 | dib8000_set_gpio(fe, 6, 0, 0); | 1707 | state->dib8000_ops.set_gpio(fe, 6, 0, 0); |
| 1609 | } | 1708 | } |
| 1610 | } while (tune_state < CT_AGC_STOP); | 1709 | } while (tune_state < CT_AGC_STOP); |
| 1611 | 1710 | ||
| 1612 | deb_info("switching to PWM AGC\n"); | 1711 | deb_info("switching to PWM AGC\n"); |
| 1613 | dib0090_pwm_gain_reset(fe); | 1712 | dib0090_pwm_gain_reset(fe); |
| 1614 | dib8000_pwm_agc_reset(fe); | 1713 | state->dib8000_ops.pwm_agc_reset(fe); |
| 1615 | dib8000_set_tune_state(fe, CT_DEMOD_START); | 1714 | state->dib8000_ops.set_tune_state(fe, CT_DEMOD_START); |
| 1616 | } else { | 1715 | } else { |
| 1617 | /* for everything else than CBAND we are using standard AGC */ | 1716 | /* for everything else than CBAND we are using standard AGC */ |
| 1618 | deb_info("not tuning in CBAND - standard AGC startup\n"); | 1717 | deb_info("not tuning in CBAND - standard AGC startup\n"); |
| @@ -1625,7 +1724,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) | |||
| 1625 | static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) | 1724 | static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) |
| 1626 | { | 1725 | { |
| 1627 | struct dib0700_adapter_state *st = adap->priv; | 1726 | struct dib0700_adapter_state *st = adap->priv; |
| 1628 | struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); | 1727 | struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); |
| 1629 | 1728 | ||
| 1630 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) | 1729 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) |
| 1631 | return -ENODEV; | 1730 | return -ENODEV; |
| @@ -1637,6 +1736,11 @@ static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 1637 | 1736 | ||
| 1638 | static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) | 1737 | static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) |
| 1639 | { | 1738 | { |
| 1739 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1740 | |||
| 1741 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) | ||
| 1742 | return -ENODEV; | ||
| 1743 | |||
| 1640 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 1744 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| 1641 | msleep(10); | 1745 | msleep(10); |
| 1642 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | 1746 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); |
| @@ -1652,9 +1756,9 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1652 | msleep(10); | 1756 | msleep(10); |
| 1653 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1757 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 1654 | 1758 | ||
| 1655 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0); | 1759 | state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0); |
| 1656 | 1760 | ||
| 1657 | adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); | 1761 | adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); |
| 1658 | 1762 | ||
| 1659 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 1763 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 1660 | } | 1764 | } |
| @@ -1663,16 +1767,16 @@ static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 1663 | { | 1767 | { |
| 1664 | struct dib0700_adapter_state *st = adap->priv; | 1768 | struct dib0700_adapter_state *st = adap->priv; |
| 1665 | struct i2c_adapter *tun_i2c; | 1769 | struct i2c_adapter *tun_i2c; |
| 1666 | struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1); | 1770 | struct dvb_frontend *fe_slave = st->dib8000_ops.get_slave_frontend(adap->fe_adap[0].fe, 1); |
| 1667 | 1771 | ||
| 1668 | if (fe_slave) { | 1772 | if (fe_slave) { |
| 1669 | tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1); | 1773 | tun_i2c = st->dib8000_ops.get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1); |
| 1670 | if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL) | 1774 | if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL) |
| 1671 | return -ENODEV; | 1775 | return -ENODEV; |
| 1672 | fe_slave->dvb = adap->fe_adap[0].fe->dvb; | 1776 | fe_slave->dvb = adap->fe_adap[0].fe->dvb; |
| 1673 | fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override; | 1777 | fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override; |
| 1674 | } | 1778 | } |
| 1675 | tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); | 1779 | tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); |
| 1676 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) | 1780 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) |
| 1677 | return -ENODEV; | 1781 | return -ENODEV; |
| 1678 | 1782 | ||
| @@ -1685,6 +1789,10 @@ static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 1685 | static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap) | 1789 | static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap) |
| 1686 | { | 1790 | { |
| 1687 | struct dvb_frontend *fe_slave; | 1791 | struct dvb_frontend *fe_slave; |
| 1792 | struct dib0700_adapter_state *state = adap->priv; | ||
| 1793 | |||
| 1794 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) | ||
| 1795 | return -ENODEV; | ||
| 1688 | 1796 | ||
| 1689 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | 1797 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); |
| 1690 | msleep(20); | 1798 | msleep(20); |
| @@ -1703,14 +1811,18 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 1703 | msleep(20); | 1811 | msleep(20); |
| 1704 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 1812 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 1705 | 1813 | ||
| 1706 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0); | 1814 | state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0); |
| 1707 | 1815 | ||
| 1708 | adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); | 1816 | adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]); |
| 1709 | if (adap->fe_adap[0].fe == NULL) | 1817 | if (adap->fe_adap[0].fe == NULL) |
| 1710 | return -ENODEV; | 1818 | return -ENODEV; |
| 1711 | 1819 | ||
| 1712 | fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]); | 1820 | /* Needed to increment refcount */ |
| 1713 | dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave); | 1821 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) |
| 1822 | return -ENODEV; | ||
| 1823 | |||
| 1824 | fe_slave = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]); | ||
| 1825 | state->dib8000_ops.set_slave_frontend(adap->fe_adap[0].fe, fe_slave); | ||
| 1714 | 1826 | ||
| 1715 | return fe_slave == NULL ? -ENODEV : 0; | 1827 | return fe_slave == NULL ? -ENODEV : 0; |
| 1716 | } | 1828 | } |
| @@ -1845,7 +1957,7 @@ static struct dib0090_wbd_slope dib8096p_wbd_table[] = { | |||
| 1845 | { 0xFFFF, 0, 0, 0, 0, 0}, | 1957 | { 0xFFFF, 0, 0, 0, 0, 0}, |
| 1846 | }; | 1958 | }; |
| 1847 | 1959 | ||
| 1848 | static const struct dib0090_config tfe8096p_dib0090_config = { | 1960 | static struct dib0090_config tfe8096p_dib0090_config = { |
| 1849 | .io.clock_khz = 12000, | 1961 | .io.clock_khz = 12000, |
| 1850 | .io.pll_bypass = 0, | 1962 | .io.pll_bypass = 0, |
| 1851 | .io.pll_range = 0, | 1963 | .io.pll_range = 0, |
| @@ -1853,8 +1965,6 @@ static const struct dib0090_config tfe8096p_dib0090_config = { | |||
| 1853 | .io.pll_loopdiv = 6, | 1965 | .io.pll_loopdiv = 6, |
| 1854 | .io.adc_clock_ratio = 0, | 1966 | .io.adc_clock_ratio = 0, |
| 1855 | .io.pll_int_loop_filt = 0, | 1967 | .io.pll_int_loop_filt = 0, |
| 1856 | .reset = dib8096p_tuner_sleep, | ||
| 1857 | .sleep = dib8096p_tuner_sleep, | ||
| 1858 | 1968 | ||
| 1859 | .freq_offset_khz_uhf = -143, | 1969 | .freq_offset_khz_uhf = -143, |
| 1860 | .freq_offset_khz_vhf = -143, | 1970 | .freq_offset_khz_vhf = -143, |
| @@ -1871,8 +1981,6 @@ static const struct dib0090_config tfe8096p_dib0090_config = { | |||
| 1871 | 1981 | ||
| 1872 | .fref_clock_ratio = 1, | 1982 | .fref_clock_ratio = 1, |
| 1873 | 1983 | ||
| 1874 | .wbd = dib8096p_wbd_table, | ||
| 1875 | |||
| 1876 | .ls_cfg_pad_drv = 0, | 1984 | .ls_cfg_pad_drv = 0, |
| 1877 | .data_tx_drv = 0, | 1985 | .data_tx_drv = 0, |
| 1878 | .low_if = NULL, | 1986 | .low_if = NULL, |
| @@ -1983,15 +2091,15 @@ static int dib8096p_agc_startup(struct dvb_frontend *fe) | |||
| 1983 | /* dib0090_get_wbd_target is returning any possible | 2091 | /* dib0090_get_wbd_target is returning any possible |
| 1984 | temperature compensated wbd-target */ | 2092 | temperature compensated wbd-target */ |
| 1985 | target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; | 2093 | target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; |
| 1986 | dib8000_set_wbd_ref(fe, target); | 2094 | state->dib8000_ops.set_wbd_ref(fe, target); |
| 1987 | 2095 | ||
| 1988 | if (dib8096p_get_best_sampling(fe, &adc) == 0) { | 2096 | if (dib8096p_get_best_sampling(fe, &adc) == 0) { |
| 1989 | pll.pll_ratio = adc.pll_loopdiv; | 2097 | pll.pll_ratio = adc.pll_loopdiv; |
| 1990 | pll.pll_prediv = adc.pll_prediv; | 2098 | pll.pll_prediv = adc.pll_prediv; |
| 1991 | 2099 | ||
| 1992 | dib0700_set_i2c_speed(adap->dev, 200); | 2100 | dib0700_set_i2c_speed(adap->dev, 200); |
| 1993 | dib8000_update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0); | 2101 | state->dib8000_ops.update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0); |
| 1994 | dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf); | 2102 | state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf); |
| 1995 | dib0700_set_i2c_speed(adap->dev, 1000); | 2103 | dib0700_set_i2c_speed(adap->dev, 1000); |
| 1996 | } | 2104 | } |
| 1997 | return 0; | 2105 | return 0; |
| @@ -2001,6 +2109,10 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 2001 | { | 2109 | { |
| 2002 | struct dib0700_state *st = adap->dev->priv; | 2110 | struct dib0700_state *st = adap->dev->priv; |
| 2003 | u32 fw_version; | 2111 | u32 fw_version; |
| 2112 | struct dib0700_adapter_state *state = adap->priv; | ||
| 2113 | |||
| 2114 | if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) | ||
| 2115 | return -ENODEV; | ||
| 2004 | 2116 | ||
| 2005 | dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL); | 2117 | dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL); |
| 2006 | if (fw_version >= 0x10200) | 2118 | if (fw_version >= 0x10200) |
| @@ -2021,10 +2133,10 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 2021 | msleep(20); | 2133 | msleep(20); |
| 2022 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 2134 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 2023 | 2135 | ||
| 2024 | dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1); | 2136 | state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1); |
| 2025 | 2137 | ||
| 2026 | adap->fe_adap[0].fe = dvb_attach(dib8000_attach, | 2138 | adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, |
| 2027 | &adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config); | 2139 | 0x80, &tfe8096p_dib8000_config); |
| 2028 | 2140 | ||
| 2029 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 2141 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 2030 | } | 2142 | } |
| @@ -2032,13 +2144,17 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 2032 | static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap) | 2144 | static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap) |
| 2033 | { | 2145 | { |
| 2034 | struct dib0700_adapter_state *st = adap->priv; | 2146 | struct dib0700_adapter_state *st = adap->priv; |
| 2035 | struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe); | 2147 | struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_tuner(adap->fe_adap[0].fe); |
| 2148 | |||
| 2149 | tfe8096p_dib0090_config.reset = st->dib8000_ops.tuner_sleep; | ||
| 2150 | tfe8096p_dib0090_config.sleep = st->dib8000_ops.tuner_sleep; | ||
| 2151 | tfe8096p_dib0090_config.wbd = dib8096p_wbd_table; | ||
| 2036 | 2152 | ||
| 2037 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, | 2153 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, |
| 2038 | &tfe8096p_dib0090_config) == NULL) | 2154 | &tfe8096p_dib0090_config) == NULL) |
| 2039 | return -ENODEV; | 2155 | return -ENODEV; |
| 2040 | 2156 | ||
| 2041 | dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 2157 | st->dib8000_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); |
| 2042 | 2158 | ||
| 2043 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; | 2159 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; |
| 2044 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup; | 2160 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup; |
| @@ -2479,14 +2595,14 @@ static int dib7090_agc_startup(struct dvb_frontend *fe) | |||
| 2479 | memset(&pll, 0, sizeof(struct dibx000_bandwidth_config)); | 2595 | memset(&pll, 0, sizeof(struct dibx000_bandwidth_config)); |
| 2480 | dib0090_pwm_gain_reset(fe); | 2596 | dib0090_pwm_gain_reset(fe); |
| 2481 | target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; | 2597 | target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2; |
| 2482 | dib7000p_set_wbd_ref(fe, target); | 2598 | state->dib7000p_ops.set_wbd_ref(fe, target); |
| 2483 | 2599 | ||
| 2484 | if (dib7090p_get_best_sampling(fe, &adc) == 0) { | 2600 | if (dib7090p_get_best_sampling(fe, &adc) == 0) { |
| 2485 | pll.pll_ratio = adc.pll_loopdiv; | 2601 | pll.pll_ratio = adc.pll_loopdiv; |
| 2486 | pll.pll_prediv = adc.pll_prediv; | 2602 | pll.pll_prediv = adc.pll_prediv; |
| 2487 | 2603 | ||
| 2488 | dib7000p_update_pll(fe, &pll); | 2604 | state->dib7000p_ops.update_pll(fe, &pll); |
| 2489 | dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf); | 2605 | state->dib7000p_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf); |
| 2490 | } | 2606 | } |
| 2491 | return 0; | 2607 | return 0; |
| 2492 | } | 2608 | } |
| @@ -2501,14 +2617,17 @@ static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart) | |||
| 2501 | 2617 | ||
| 2502 | static int tfe7790p_update_lna(struct dvb_frontend *fe, u16 agc_global) | 2618 | static int tfe7790p_update_lna(struct dvb_frontend *fe, u16 agc_global) |
| 2503 | { | 2619 | { |
| 2620 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 2621 | struct dib0700_adapter_state *state = adap->priv; | ||
| 2622 | |||
| 2504 | deb_info("update LNA: agc global=%i", agc_global); | 2623 | deb_info("update LNA: agc global=%i", agc_global); |
| 2505 | 2624 | ||
| 2506 | if (agc_global < 25000) { | 2625 | if (agc_global < 25000) { |
| 2507 | dib7000p_set_gpio(fe, 8, 0, 0); | 2626 | state->dib7000p_ops.set_gpio(fe, 8, 0, 0); |
| 2508 | dib7000p_set_agc1_min(fe, 0); | 2627 | state->dib7000p_ops.set_agc1_min(fe, 0); |
| 2509 | } else { | 2628 | } else { |
| 2510 | dib7000p_set_gpio(fe, 8, 0, 1); | 2629 | state->dib7000p_ops.set_gpio(fe, 8, 0, 1); |
| 2511 | dib7000p_set_agc1_min(fe, 32768); | 2630 | state->dib7000p_ops.set_agc1_min(fe, 32768); |
| 2512 | } | 2631 | } |
| 2513 | 2632 | ||
| 2514 | return 0; | 2633 | return 0; |
| @@ -2644,13 +2763,16 @@ static struct dib7000p_config nim7090_dib7000p_config = { | |||
| 2644 | 2763 | ||
| 2645 | static int tfe7090p_pvr_update_lna(struct dvb_frontend *fe, u16 agc_global) | 2764 | static int tfe7090p_pvr_update_lna(struct dvb_frontend *fe, u16 agc_global) |
| 2646 | { | 2765 | { |
| 2766 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
| 2767 | struct dib0700_adapter_state *state = adap->priv; | ||
| 2768 | |||
| 2647 | deb_info("TFE7090P-PVR update LNA: agc global=%i", agc_global); | 2769 | deb_info("TFE7090P-PVR update LNA: agc global=%i", agc_global); |
| 2648 | if (agc_global < 25000) { | 2770 | if (agc_global < 25000) { |
| 2649 | dib7000p_set_gpio(fe, 5, 0, 0); | 2771 | state->dib7000p_ops.set_gpio(fe, 5, 0, 0); |
| 2650 | dib7000p_set_agc1_min(fe, 0); | 2772 | state->dib7000p_ops.set_agc1_min(fe, 0); |
| 2651 | } else { | 2773 | } else { |
| 2652 | dib7000p_set_gpio(fe, 5, 0, 1); | 2774 | state->dib7000p_ops.set_gpio(fe, 5, 0, 1); |
| 2653 | dib7000p_set_agc1_min(fe, 32768); | 2775 | state->dib7000p_ops.set_agc1_min(fe, 32768); |
| 2654 | } | 2776 | } |
| 2655 | 2777 | ||
| 2656 | return 0; | 2778 | return 0; |
| @@ -2714,7 +2836,7 @@ static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = { | |||
| 2714 | } | 2836 | } |
| 2715 | }; | 2837 | }; |
| 2716 | 2838 | ||
| 2717 | static const struct dib0090_config nim7090_dib0090_config = { | 2839 | static struct dib0090_config nim7090_dib0090_config = { |
| 2718 | .io.clock_khz = 12000, | 2840 | .io.clock_khz = 12000, |
| 2719 | .io.pll_bypass = 0, | 2841 | .io.pll_bypass = 0, |
| 2720 | .io.pll_range = 0, | 2842 | .io.pll_range = 0, |
| @@ -2722,14 +2844,10 @@ static const struct dib0090_config nim7090_dib0090_config = { | |||
| 2722 | .io.pll_loopdiv = 6, | 2844 | .io.pll_loopdiv = 6, |
| 2723 | .io.adc_clock_ratio = 0, | 2845 | .io.adc_clock_ratio = 0, |
| 2724 | .io.pll_int_loop_filt = 0, | 2846 | .io.pll_int_loop_filt = 0, |
| 2725 | .reset = dib7090_tuner_sleep, | ||
| 2726 | .sleep = dib7090_tuner_sleep, | ||
| 2727 | 2847 | ||
| 2728 | .freq_offset_khz_uhf = 0, | 2848 | .freq_offset_khz_uhf = 0, |
| 2729 | .freq_offset_khz_vhf = 0, | 2849 | .freq_offset_khz_vhf = 0, |
| 2730 | 2850 | ||
| 2731 | .get_adc_power = dib7090_get_adc_power, | ||
| 2732 | |||
| 2733 | .clkouttobamse = 1, | 2851 | .clkouttobamse = 1, |
| 2734 | .analog_output = 0, | 2852 | .analog_output = 0, |
| 2735 | 2853 | ||
| @@ -2776,7 +2894,7 @@ static struct dib7000p_config tfe7790p_dib7000p_config = { | |||
| 2776 | .enMpegOutput = 1, | 2894 | .enMpegOutput = 1, |
| 2777 | }; | 2895 | }; |
| 2778 | 2896 | ||
| 2779 | static const struct dib0090_config tfe7790p_dib0090_config = { | 2897 | static struct dib0090_config tfe7790p_dib0090_config = { |
| 2780 | .io.clock_khz = 12000, | 2898 | .io.clock_khz = 12000, |
| 2781 | .io.pll_bypass = 0, | 2899 | .io.pll_bypass = 0, |
| 2782 | .io.pll_range = 0, | 2900 | .io.pll_range = 0, |
| @@ -2784,14 +2902,10 @@ static const struct dib0090_config tfe7790p_dib0090_config = { | |||
| 2784 | .io.pll_loopdiv = 6, | 2902 | .io.pll_loopdiv = 6, |
| 2785 | .io.adc_clock_ratio = 0, | 2903 | .io.adc_clock_ratio = 0, |
| 2786 | .io.pll_int_loop_filt = 0, | 2904 | .io.pll_int_loop_filt = 0, |
| 2787 | .reset = dib7090_tuner_sleep, | ||
| 2788 | .sleep = dib7090_tuner_sleep, | ||
| 2789 | 2905 | ||
| 2790 | .freq_offset_khz_uhf = 0, | 2906 | .freq_offset_khz_uhf = 0, |
| 2791 | .freq_offset_khz_vhf = 0, | 2907 | .freq_offset_khz_vhf = 0, |
| 2792 | 2908 | ||
| 2793 | .get_adc_power = dib7090_get_adc_power, | ||
| 2794 | |||
| 2795 | .clkouttobamse = 1, | 2909 | .clkouttobamse = 1, |
| 2796 | .analog_output = 0, | 2910 | .analog_output = 0, |
| 2797 | 2911 | ||
| @@ -2813,7 +2927,7 @@ static const struct dib0090_config tfe7790p_dib0090_config = { | |||
| 2813 | .force_crystal_mode = 1, | 2927 | .force_crystal_mode = 1, |
| 2814 | }; | 2928 | }; |
| 2815 | 2929 | ||
| 2816 | static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { | 2930 | static struct dib0090_config tfe7090pvr_dib0090_config[2] = { |
| 2817 | { | 2931 | { |
| 2818 | .io.clock_khz = 12000, | 2932 | .io.clock_khz = 12000, |
| 2819 | .io.pll_bypass = 0, | 2933 | .io.pll_bypass = 0, |
| @@ -2822,14 +2936,10 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { | |||
| 2822 | .io.pll_loopdiv = 6, | 2936 | .io.pll_loopdiv = 6, |
| 2823 | .io.adc_clock_ratio = 0, | 2937 | .io.adc_clock_ratio = 0, |
| 2824 | .io.pll_int_loop_filt = 0, | 2938 | .io.pll_int_loop_filt = 0, |
| 2825 | .reset = dib7090_tuner_sleep, | ||
| 2826 | .sleep = dib7090_tuner_sleep, | ||
| 2827 | 2939 | ||
| 2828 | .freq_offset_khz_uhf = 50, | 2940 | .freq_offset_khz_uhf = 50, |
| 2829 | .freq_offset_khz_vhf = 70, | 2941 | .freq_offset_khz_vhf = 70, |
| 2830 | 2942 | ||
| 2831 | .get_adc_power = dib7090_get_adc_power, | ||
| 2832 | |||
| 2833 | .clkouttobamse = 1, | 2943 | .clkouttobamse = 1, |
| 2834 | .analog_output = 0, | 2944 | .analog_output = 0, |
| 2835 | 2945 | ||
| @@ -2854,14 +2964,10 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { | |||
| 2854 | .io.pll_loopdiv = 6, | 2964 | .io.pll_loopdiv = 6, |
| 2855 | .io.adc_clock_ratio = 0, | 2965 | .io.adc_clock_ratio = 0, |
| 2856 | .io.pll_int_loop_filt = 0, | 2966 | .io.pll_int_loop_filt = 0, |
| 2857 | .reset = dib7090_tuner_sleep, | ||
| 2858 | .sleep = dib7090_tuner_sleep, | ||
| 2859 | 2967 | ||
| 2860 | .freq_offset_khz_uhf = -50, | 2968 | .freq_offset_khz_uhf = -50, |
| 2861 | .freq_offset_khz_vhf = -70, | 2969 | .freq_offset_khz_vhf = -70, |
| 2862 | 2970 | ||
| 2863 | .get_adc_power = dib7090_get_adc_power, | ||
| 2864 | |||
| 2865 | .clkouttobamse = 1, | 2971 | .clkouttobamse = 1, |
| 2866 | .analog_output = 0, | 2972 | .analog_output = 0, |
| 2867 | 2973 | ||
| @@ -2883,6 +2989,11 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = { | |||
| 2883 | 2989 | ||
| 2884 | static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) | 2990 | static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) |
| 2885 | { | 2991 | { |
| 2992 | struct dib0700_adapter_state *state = adap->priv; | ||
| 2993 | |||
| 2994 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 2995 | return -ENODEV; | ||
| 2996 | |||
| 2886 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); | 2997 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); |
| 2887 | msleep(20); | 2998 | msleep(20); |
| 2888 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); | 2999 | dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); |
| @@ -2895,11 +3006,12 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 2895 | msleep(20); | 3006 | msleep(20); |
| 2896 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 3007 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 2897 | 3008 | ||
| 2898 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { | 3009 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) { |
| 2899 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | 3010 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); |
| 3011 | dvb_detach(&state->dib7000p_ops); | ||
| 2900 | return -ENODEV; | 3012 | return -ENODEV; |
| 2901 | } | 3013 | } |
| 2902 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); | 3014 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config); |
| 2903 | 3015 | ||
| 2904 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 3016 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 2905 | } | 3017 | } |
| @@ -2907,12 +3019,16 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 2907 | static int nim7090_tuner_attach(struct dvb_usb_adapter *adap) | 3019 | static int nim7090_tuner_attach(struct dvb_usb_adapter *adap) |
| 2908 | { | 3020 | { |
| 2909 | struct dib0700_adapter_state *st = adap->priv; | 3021 | struct dib0700_adapter_state *st = adap->priv; |
| 2910 | struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe); | 3022 | struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe); |
| 3023 | |||
| 3024 | nim7090_dib0090_config.reset = st->dib7000p_ops.tuner_sleep, | ||
| 3025 | nim7090_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep, | ||
| 3026 | nim7090_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power; | ||
| 2911 | 3027 | ||
| 2912 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL) | 3028 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL) |
| 2913 | return -ENODEV; | 3029 | return -ENODEV; |
| 2914 | 3030 | ||
| 2915 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 3031 | st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); |
| 2916 | 3032 | ||
| 2917 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; | 3033 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; |
| 2918 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; | 3034 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; |
| @@ -2922,6 +3038,10 @@ static int nim7090_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 2922 | static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) | 3038 | static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) |
| 2923 | { | 3039 | { |
| 2924 | struct dib0700_state *st = adap->dev->priv; | 3040 | struct dib0700_state *st = adap->dev->priv; |
| 3041 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3042 | |||
| 3043 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 3044 | return -ENODEV; | ||
| 2925 | 3045 | ||
| 2926 | /* The TFE7090 requires the dib0700 to not be in master mode */ | 3046 | /* The TFE7090 requires the dib0700 to not be in master mode */ |
| 2927 | st->disable_streaming_master_mode = 1; | 3047 | st->disable_streaming_master_mode = 1; |
| @@ -2939,17 +3059,18 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) | |||
| 2939 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 3059 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 2940 | 3060 | ||
| 2941 | /* initialize IC 0 */ | 3061 | /* initialize IC 0 */ |
| 2942 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { | 3062 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) { |
| 2943 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | 3063 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); |
| 3064 | dvb_detach(&state->dib7000p_ops); | ||
| 2944 | return -ENODEV; | 3065 | return -ENODEV; |
| 2945 | } | 3066 | } |
| 2946 | 3067 | ||
| 2947 | dib0700_set_i2c_speed(adap->dev, 340); | 3068 | dib0700_set_i2c_speed(adap->dev, 340); |
| 2948 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]); | 3069 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]); |
| 2949 | if (adap->fe_adap[0].fe == NULL) | 3070 | if (adap->fe_adap[0].fe == NULL) |
| 2950 | return -ENODEV; | 3071 | return -ENODEV; |
| 2951 | 3072 | ||
| 2952 | dib7090_slave_reset(adap->fe_adap[0].fe); | 3073 | state->dib7000p_ops.slave_reset(adap->fe_adap[0].fe); |
| 2953 | 3074 | ||
| 2954 | return 0; | 3075 | return 0; |
| 2955 | } | 3076 | } |
| @@ -2957,19 +3078,24 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap) | |||
| 2957 | static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) | 3078 | static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) |
| 2958 | { | 3079 | { |
| 2959 | struct i2c_adapter *i2c; | 3080 | struct i2c_adapter *i2c; |
| 3081 | struct dib0700_adapter_state *state = adap->priv; | ||
| 2960 | 3082 | ||
| 2961 | if (adap->dev->adapter[0].fe_adap[0].fe == NULL) { | 3083 | if (adap->dev->adapter[0].fe_adap[0].fe == NULL) { |
| 2962 | err("the master dib7090 has to be initialized first"); | 3084 | err("the master dib7090 has to be initialized first"); |
| 2963 | return -ENODEV; /* the master device has not been initialized */ | 3085 | return -ENODEV; /* the master device has not been initialized */ |
| 2964 | } | 3086 | } |
| 2965 | 3087 | ||
| 2966 | i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); | 3088 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) |
| 2967 | if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { | 3089 | return -ENODEV; |
| 2968 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__); | 3090 | |
| 3091 | i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1); | ||
| 3092 | if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) { | ||
| 3093 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__); | ||
| 3094 | dvb_detach(&state->dib7000p_ops); | ||
| 2969 | return -ENODEV; | 3095 | return -ENODEV; |
| 2970 | } | 3096 | } |
| 2971 | 3097 | ||
| 2972 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]); | 3098 | adap->fe_adap[0].fe = state->dib7000p_ops.init(i2c, 0x92, &tfe7090pvr_dib7000p_config[1]); |
| 2973 | dib0700_set_i2c_speed(adap->dev, 200); | 3099 | dib0700_set_i2c_speed(adap->dev, 200); |
| 2974 | 3100 | ||
| 2975 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 3101 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| @@ -2978,12 +3104,16 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap) | |||
| 2978 | static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap) | 3104 | static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap) |
| 2979 | { | 3105 | { |
| 2980 | struct dib0700_adapter_state *st = adap->priv; | 3106 | struct dib0700_adapter_state *st = adap->priv; |
| 2981 | struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe); | 3107 | struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe); |
| 3108 | |||
| 3109 | tfe7090pvr_dib0090_config[0].reset = st->dib7000p_ops.tuner_sleep; | ||
| 3110 | tfe7090pvr_dib0090_config[0].sleep = st->dib7000p_ops.tuner_sleep; | ||
| 3111 | tfe7090pvr_dib0090_config[0].get_adc_power = st->dib7000p_ops.get_adc_power; | ||
| 2982 | 3112 | ||
| 2983 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL) | 3113 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL) |
| 2984 | return -ENODEV; | 3114 | return -ENODEV; |
| 2985 | 3115 | ||
| 2986 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 3116 | st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); |
| 2987 | 3117 | ||
| 2988 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; | 3118 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; |
| 2989 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; | 3119 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; |
| @@ -2993,12 +3123,16 @@ static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap) | |||
| 2993 | static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap) | 3123 | static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap) |
| 2994 | { | 3124 | { |
| 2995 | struct dib0700_adapter_state *st = adap->priv; | 3125 | struct dib0700_adapter_state *st = adap->priv; |
| 2996 | struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe); | 3126 | struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe); |
| 3127 | |||
| 3128 | tfe7090pvr_dib0090_config[1].reset = st->dib7000p_ops.tuner_sleep; | ||
| 3129 | tfe7090pvr_dib0090_config[1].sleep = st->dib7000p_ops.tuner_sleep; | ||
| 3130 | tfe7090pvr_dib0090_config[1].get_adc_power = st->dib7000p_ops.get_adc_power; | ||
| 2997 | 3131 | ||
| 2998 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL) | 3132 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL) |
| 2999 | return -ENODEV; | 3133 | return -ENODEV; |
| 3000 | 3134 | ||
| 3001 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 3135 | st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); |
| 3002 | 3136 | ||
| 3003 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; | 3137 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; |
| 3004 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; | 3138 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; |
| @@ -3008,6 +3142,10 @@ static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap) | |||
| 3008 | static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap) | 3142 | static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap) |
| 3009 | { | 3143 | { |
| 3010 | struct dib0700_state *st = adap->dev->priv; | 3144 | struct dib0700_state *st = adap->dev->priv; |
| 3145 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3146 | |||
| 3147 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 3148 | return -ENODEV; | ||
| 3011 | 3149 | ||
| 3012 | /* The TFE7790P requires the dib0700 to not be in master mode */ | 3150 | /* The TFE7790P requires the dib0700 to not be in master mode */ |
| 3013 | st->disable_streaming_master_mode = 1; | 3151 | st->disable_streaming_master_mode = 1; |
| @@ -3024,13 +3162,14 @@ static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 3024 | msleep(20); | 3162 | msleep(20); |
| 3025 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 3163 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 3026 | 3164 | ||
| 3027 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, | 3165 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, |
| 3028 | 1, 0x10, &tfe7790p_dib7000p_config) != 0) { | 3166 | 1, 0x10, &tfe7790p_dib7000p_config) != 0) { |
| 3029 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | 3167 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", |
| 3030 | __func__); | 3168 | __func__); |
| 3169 | dvb_detach(&state->dib7000p_ops); | ||
| 3031 | return -ENODEV; | 3170 | return -ENODEV; |
| 3032 | } | 3171 | } |
| 3033 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, | 3172 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, |
| 3034 | 0x80, &tfe7790p_dib7000p_config); | 3173 | 0x80, &tfe7790p_dib7000p_config); |
| 3035 | 3174 | ||
| 3036 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 3175 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| @@ -3040,13 +3179,18 @@ static int tfe7790p_tuner_attach(struct dvb_usb_adapter *adap) | |||
| 3040 | { | 3179 | { |
| 3041 | struct dib0700_adapter_state *st = adap->priv; | 3180 | struct dib0700_adapter_state *st = adap->priv; |
| 3042 | struct i2c_adapter *tun_i2c = | 3181 | struct i2c_adapter *tun_i2c = |
| 3043 | dib7090_get_i2c_tuner(adap->fe_adap[0].fe); | 3182 | st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe); |
| 3183 | |||
| 3184 | |||
| 3185 | tfe7790p_dib0090_config.reset = st->dib7000p_ops.tuner_sleep; | ||
| 3186 | tfe7790p_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep; | ||
| 3187 | tfe7790p_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power; | ||
| 3044 | 3188 | ||
| 3045 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, | 3189 | if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, |
| 3046 | &tfe7790p_dib0090_config) == NULL) | 3190 | &tfe7790p_dib0090_config) == NULL) |
| 3047 | return -ENODEV; | 3191 | return -ENODEV; |
| 3048 | 3192 | ||
| 3049 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 3193 | st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); |
| 3050 | 3194 | ||
| 3051 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; | 3195 | st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; |
| 3052 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; | 3196 | adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup; |
| @@ -3103,25 +3247,36 @@ static void stk7070pd_init(struct dvb_usb_device *dev) | |||
| 3103 | 3247 | ||
| 3104 | static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) | 3248 | static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap) |
| 3105 | { | 3249 | { |
| 3250 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3251 | |||
| 3252 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 3253 | return -ENODEV; | ||
| 3254 | |||
| 3106 | stk7070pd_init(adap->dev); | 3255 | stk7070pd_init(adap->dev); |
| 3107 | 3256 | ||
| 3108 | msleep(10); | 3257 | msleep(10); |
| 3109 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); | 3258 | dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); |
| 3110 | 3259 | ||
| 3111 | if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, | 3260 | if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18, |
| 3112 | stk7070pd_dib7000p_config) != 0) { | 3261 | stk7070pd_dib7000p_config) != 0) { |
| 3113 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | 3262 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", |
| 3114 | __func__); | 3263 | __func__); |
| 3264 | dvb_detach(&state->dib7000p_ops); | ||
| 3115 | return -ENODEV; | 3265 | return -ENODEV; |
| 3116 | } | 3266 | } |
| 3117 | 3267 | ||
| 3118 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]); | 3268 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]); |
| 3119 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 3269 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 3120 | } | 3270 | } |
| 3121 | 3271 | ||
| 3122 | static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) | 3272 | static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap) |
| 3123 | { | 3273 | { |
| 3124 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]); | 3274 | struct dib0700_adapter_state *state = adap->priv; |
| 3275 | |||
| 3276 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 3277 | return -ENODEV; | ||
| 3278 | |||
| 3279 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]); | ||
| 3125 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; | 3280 | return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; |
| 3126 | } | 3281 | } |
| 3127 | 3282 | ||
| @@ -3164,6 +3319,10 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 3164 | { | 3319 | { |
| 3165 | struct dvb_usb_device *dev = adap->dev; | 3320 | struct dvb_usb_device *dev = adap->dev; |
| 3166 | struct dib0700_state *st = dev->priv; | 3321 | struct dib0700_state *st = dev->priv; |
| 3322 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3323 | |||
| 3324 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 3325 | return -ENODEV; | ||
| 3167 | 3326 | ||
| 3168 | if (adap->id == 0) { | 3327 | if (adap->id == 0) { |
| 3169 | stk7070pd_init(dev); | 3328 | stk7070pd_init(dev); |
| @@ -3173,15 +3332,16 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 3173 | dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0); | 3332 | dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0); |
| 3174 | dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1); | 3333 | dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1); |
| 3175 | 3334 | ||
| 3176 | if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18, | 3335 | if (state->dib7000p_ops.i2c_enumeration(&dev->i2c_adap, 2, 18, |
| 3177 | stk7070pd_dib7000p_config) != 0) { | 3336 | stk7070pd_dib7000p_config) != 0) { |
| 3178 | err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", | 3337 | err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", |
| 3179 | __func__); | 3338 | __func__); |
| 3339 | dvb_detach(&state->dib7000p_ops); | ||
| 3180 | return -ENODEV; | 3340 | return -ENODEV; |
| 3181 | } | 3341 | } |
| 3182 | } | 3342 | } |
| 3183 | 3343 | ||
| 3184 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap, | 3344 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&dev->i2c_adap, |
| 3185 | adap->id == 0 ? 0x80 : 0x82, | 3345 | adap->id == 0 ? 0x80 : 0x82, |
| 3186 | &stk7070pd_dib7000p_config[adap->id]); | 3346 | &stk7070pd_dib7000p_config[adap->id]); |
| 3187 | 3347 | ||
| @@ -3291,12 +3451,13 @@ static int dib0700_xc4000_tuner_callback(void *priv, int component, | |||
| 3291 | int command, int arg) | 3451 | int command, int arg) |
| 3292 | { | 3452 | { |
| 3293 | struct dvb_usb_adapter *adap = priv; | 3453 | struct dvb_usb_adapter *adap = priv; |
| 3454 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3294 | 3455 | ||
| 3295 | if (command == XC4000_TUNER_RESET) { | 3456 | if (command == XC4000_TUNER_RESET) { |
| 3296 | /* Reset the tuner */ | 3457 | /* Reset the tuner */ |
| 3297 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); | 3458 | state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0); |
| 3298 | msleep(10); | 3459 | msleep(10); |
| 3299 | dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1); | 3460 | state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1); |
| 3300 | } else { | 3461 | } else { |
| 3301 | err("xc4000: unknown tuner callback command: %d\n", command); | 3462 | err("xc4000: unknown tuner callback command: %d\n", command); |
| 3302 | return -EINVAL; | 3463 | return -EINVAL; |
| @@ -3374,6 +3535,10 @@ static struct dib7000p_config pctv_340e_config = { | |||
| 3374 | static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) | 3535 | static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) |
| 3375 | { | 3536 | { |
| 3376 | struct dib0700_state *st = adap->dev->priv; | 3537 | struct dib0700_state *st = adap->dev->priv; |
| 3538 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3539 | |||
| 3540 | if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops)) | ||
| 3541 | return -ENODEV; | ||
| 3377 | 3542 | ||
| 3378 | /* Power Supply on */ | 3543 | /* Power Supply on */ |
| 3379 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); | 3544 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); |
| @@ -3397,12 +3562,13 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap) | |||
| 3397 | 3562 | ||
| 3398 | msleep(500); | 3563 | msleep(500); |
| 3399 | 3564 | ||
| 3400 | if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) { | 3565 | if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) { |
| 3401 | /* Demodulator not found for some reason? */ | 3566 | /* Demodulator not found for some reason? */ |
| 3567 | dvb_detach(&state->dib7000p_ops); | ||
| 3402 | return -ENODEV; | 3568 | return -ENODEV; |
| 3403 | } | 3569 | } |
| 3404 | 3570 | ||
| 3405 | adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12, | 3571 | adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x12, |
| 3406 | &pctv_340e_config); | 3572 | &pctv_340e_config); |
| 3407 | st->is_dib7000pc = 1; | 3573 | st->is_dib7000pc = 1; |
| 3408 | 3574 | ||
| @@ -3420,9 +3586,10 @@ static struct xc4000_config dib7000p_xc4000_tunerconfig = { | |||
| 3420 | static int xc4000_tuner_attach(struct dvb_usb_adapter *adap) | 3586 | static int xc4000_tuner_attach(struct dvb_usb_adapter *adap) |
| 3421 | { | 3587 | { |
| 3422 | struct i2c_adapter *tun_i2c; | 3588 | struct i2c_adapter *tun_i2c; |
| 3589 | struct dib0700_adapter_state *state = adap->priv; | ||
| 3423 | 3590 | ||
| 3424 | /* The xc4000 is not on the main i2c bus */ | 3591 | /* The xc4000 is not on the main i2c bus */ |
| 3425 | tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, | 3592 | tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, |
| 3426 | DIBX000_I2C_INTERFACE_TUNER, 1); | 3593 | DIBX000_I2C_INTERFACE_TUNER, 1); |
| 3427 | if (tun_i2c == NULL) { | 3594 | if (tun_i2c == NULL) { |
| 3428 | printk(KERN_ERR "Could not reach tuner i2c bus\n"); | 3595 | printk(KERN_ERR "Could not reach tuner i2c bus\n"); |
| @@ -3636,6 +3803,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
| 3636 | 3803 | ||
| 3637 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), | 3804 | DIB0700_DEFAULT_STREAMING_CONFIG(0x02), |
| 3638 | }}, | 3805 | }}, |
| 3806 | .size_of_priv = sizeof(struct dib0700_adapter_state), | ||
| 3639 | }, | 3807 | }, |
| 3640 | }, | 3808 | }, |
| 3641 | 3809 | ||
diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index e47c321b3ffc..32ab1392313f 100644 --- a/drivers/media/usb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h | |||
| @@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * i2c read | 38 | * i2c read |
| 39 | * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word | 39 | * bulk write: 0x02 ((7bit i2c_addr << 1) | 0x01) register_bytes length_word |
| 40 | * bulk read: byte_buffer (length_word bytes) | 40 | * bulk read: byte_buffer (length_word bytes) |
| 41 | */ | 41 | */ |
| 42 | #define DIBUSB_REQ_I2C_READ 0x02 | 42 | #define DIBUSB_REQ_I2C_READ 0x02 |
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 4058aea9272f..7b5dae3077f6 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c | |||
| @@ -272,7 +272,7 @@ static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d) | |||
| 272 | dev->driver_name = d->props.rc.core.module_name; | 272 | dev->driver_name = d->props.rc.core.module_name; |
| 273 | dev->map_name = d->props.rc.core.rc_codes; | 273 | dev->map_name = d->props.rc.core.rc_codes; |
| 274 | dev->change_protocol = d->props.rc.core.change_protocol; | 274 | dev->change_protocol = d->props.rc.core.change_protocol; |
| 275 | rc_set_allowed_protocols(dev, d->props.rc.core.allowed_protos); | 275 | dev->allowed_protocols = d->props.rc.core.allowed_protos; |
| 276 | dev->driver_type = d->props.rc.core.driver_type; | 276 | dev->driver_type = d->props.rc.core.driver_type; |
| 277 | usb_to_input_id(d->udev, &dev->input_id); | 277 | usb_to_input_id(d->udev, &dev->input_id); |
| 278 | dev->input_name = "IR-receiver inside an USB DVB receiver"; | 278 | dev->input_name = "IR-receiver inside an USB DVB receiver"; |
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index ae0f56a32e4d..2add8c507ec9 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c | |||
| @@ -1109,6 +1109,7 @@ static struct ds3000_config su3000_ds3000_config = { | |||
| 1109 | static struct cxd2820r_config cxd2820r_config = { | 1109 | static struct cxd2820r_config cxd2820r_config = { |
| 1110 | .i2c_address = 0x6c, /* (0xd8 >> 1) */ | 1110 | .i2c_address = 0x6c, /* (0xd8 >> 1) */ |
| 1111 | .ts_mode = 0x38, | 1111 | .ts_mode = 0x38, |
| 1112 | .ts_clock_inv = 1, | ||
| 1112 | }; | 1113 | }; |
| 1113 | 1114 | ||
| 1114 | static struct tda18271_config tda18271_config = { | 1115 | static struct tda18271_config tda18271_config = { |
| @@ -1387,20 +1388,27 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d) | |||
| 1387 | 1388 | ||
| 1388 | static int t220_frontend_attach(struct dvb_usb_adapter *d) | 1389 | static int t220_frontend_attach(struct dvb_usb_adapter *d) |
| 1389 | { | 1390 | { |
| 1390 | u8 obuf[3] = { 0xe, 0x80, 0 }; | 1391 | u8 obuf[3] = { 0xe, 0x87, 0 }; |
| 1391 | u8 ibuf[] = { 0 }; | 1392 | u8 ibuf[] = { 0 }; |
| 1392 | 1393 | ||
| 1393 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) | 1394 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) |
| 1394 | err("command 0x0e transfer failed."); | 1395 | err("command 0x0e transfer failed."); |
| 1395 | 1396 | ||
| 1396 | obuf[0] = 0xe; | 1397 | obuf[0] = 0xe; |
| 1397 | obuf[1] = 0x83; | 1398 | obuf[1] = 0x86; |
| 1399 | obuf[2] = 1; | ||
| 1400 | |||
| 1401 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) | ||
| 1402 | err("command 0x0e transfer failed."); | ||
| 1403 | |||
| 1404 | obuf[0] = 0xe; | ||
| 1405 | obuf[1] = 0x80; | ||
| 1398 | obuf[2] = 0; | 1406 | obuf[2] = 0; |
| 1399 | 1407 | ||
| 1400 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) | 1408 | if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) |
| 1401 | err("command 0x0e transfer failed."); | 1409 | err("command 0x0e transfer failed."); |
| 1402 | 1410 | ||
| 1403 | msleep(100); | 1411 | msleep(50); |
| 1404 | 1412 | ||
| 1405 | obuf[0] = 0xe; | 1413 | obuf[0] = 0xe; |
| 1406 | obuf[1] = 0x80; | 1414 | obuf[1] = 0x80; |
| @@ -1482,7 +1490,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d) | |||
| 1482 | if (msg.buf[0] != 0xff) { | 1490 | if (msg.buf[0] != 0xff) { |
| 1483 | deb_rc("%s: rc code: %x, %x\n", | 1491 | deb_rc("%s: rc code: %x, %x\n", |
| 1484 | __func__, key[0], key[1]); | 1492 | __func__, key[0], key[1]); |
| 1485 | rc_keydown(d->rc_dev, key[0], 1); | 1493 | rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0], 0); |
| 1486 | } | 1494 | } |
| 1487 | } | 1495 | } |
| 1488 | 1496 | ||
| @@ -1503,7 +1511,7 @@ static int prof_rc_query(struct dvb_usb_device *d) | |||
| 1503 | if (msg.buf[0] != 0xff) { | 1511 | if (msg.buf[0] != 0xff) { |
| 1504 | deb_rc("%s: rc code: %x, %x\n", | 1512 | deb_rc("%s: rc code: %x, %x\n", |
| 1505 | __func__, key[0], key[1]); | 1513 | __func__, key[0], key[1]); |
| 1506 | rc_keydown(d->rc_dev, key[0]^0xff, 1); | 1514 | rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, key[0]^0xff, 0); |
| 1507 | } | 1515 | } |
| 1508 | } | 1516 | } |
| 1509 | 1517 | ||
| @@ -1524,7 +1532,8 @@ static int su3000_rc_query(struct dvb_usb_device *d) | |||
| 1524 | if (msg.buf[0] != 0xff) { | 1532 | if (msg.buf[0] != 0xff) { |
| 1525 | deb_rc("%s: rc code: %x, %x\n", | 1533 | deb_rc("%s: rc code: %x, %x\n", |
| 1526 | __func__, key[0], key[1]); | 1534 | __func__, key[0], key[1]); |
| 1527 | rc_keydown(d->rc_dev, key[1] << 8 | key[0], 1); | 1535 | rc_keydown(d->rc_dev, RC_TYPE_RC5, |
| 1536 | RC_SCANCODE_RC5(key[1], key[0]), 0); | ||
| 1528 | } | 1537 | } |
| 1529 | } | 1538 | } |
| 1530 | 1539 | ||
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c index 0306cb778df4..abf8ab2e02e5 100644 --- a/drivers/media/usb/dvb-usb/m920x.c +++ b/drivers/media/usb/dvb-usb/m920x.c | |||
| @@ -245,7 +245,7 @@ static int m920x_rc_core_query(struct dvb_usb_device *d) | |||
| 245 | else if (state == REMOTE_KEY_REPEAT) | 245 | else if (state == REMOTE_KEY_REPEAT) |
| 246 | rc_repeat(d->rc_dev); | 246 | rc_repeat(d->rc_dev); |
| 247 | else | 247 | else |
| 248 | rc_keydown(d->rc_dev, rc_state[1], 0); | 248 | rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, rc_state[1], 0); |
| 249 | 249 | ||
| 250 | out: | 250 | out: |
| 251 | kfree(rc_state); | 251 | kfree(rc_state); |
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index 449a99605a87..bdfe8963591c 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c | |||
| @@ -565,12 +565,12 @@ static int pctv452e_rc_query(struct dvb_usb_device *d) | |||
| 565 | 565 | ||
| 566 | if ((rx[3] == 9) && (rx[12] & 0x01)) { | 566 | if ((rx[3] == 9) && (rx[12] & 0x01)) { |
| 567 | /* got a "press" event */ | 567 | /* got a "press" event */ |
| 568 | state->last_rc_key = (rx[7] << 8) | rx[6]; | 568 | state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]); |
| 569 | if (debug > 2) | 569 | if (debug > 2) |
| 570 | info("%s: cmd=0x%02x sys=0x%02x\n", | 570 | info("%s: cmd=0x%02x sys=0x%02x\n", |
| 571 | __func__, rx[6], rx[7]); | 571 | __func__, rx[6], rx[7]); |
| 572 | 572 | ||
| 573 | rc_keydown(d->rc_dev, state->last_rc_key, 0); | 573 | rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0); |
| 574 | } else if (state->last_rc_key) { | 574 | } else if (state->last_rc_key) { |
| 575 | rc_keyup(d->rc_dev); | 575 | rc_keyup(d->rc_dev); |
| 576 | state->last_rc_key = 0; | 576 | state->last_rc_key = 0; |
| @@ -927,7 +927,7 @@ static struct dvb_usb_device_properties pctv452e_properties = { | |||
| 927 | 927 | ||
| 928 | .rc.core = { | 928 | .rc.core = { |
| 929 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, | 929 | .rc_codes = RC_MAP_DIB0700_RC5_TABLE, |
| 930 | .allowed_protos = RC_BIT_UNKNOWN, | 930 | .allowed_protos = RC_BIT_RC5, |
| 931 | .rc_query = pctv452e_rc_query, | 931 | .rc_query = pctv452e_rc_query, |
| 932 | .rc_interval = 100, | 932 | .rc_interval = 100, |
| 933 | }, | 933 | }, |
| @@ -980,7 +980,7 @@ static struct dvb_usb_device_properties tt_connect_s2_3600_properties = { | |||
| 980 | 980 | ||
| 981 | .rc.core = { | 981 | .rc.core = { |
| 982 | .rc_codes = RC_MAP_TT_1500, | 982 | .rc_codes = RC_MAP_TT_1500, |
| 983 | .allowed_protos = RC_BIT_UNKNOWN, | 983 | .allowed_protos = RC_BIT_RC5, |
| 984 | .rc_query = pctv452e_rc_query, | 984 | .rc_query = pctv452e_rc_query, |
| 985 | .rc_interval = 100, | 985 | .rc_interval = 100, |
| 986 | }, | 986 | }, |
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index d947e0379008..6b0b8b6b9e2a 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c | |||
| @@ -710,7 +710,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = { | |||
| 710 | .isoc = { | 710 | .isoc = { |
| 711 | .framesperurb = 32, | 711 | .framesperurb = 32, |
| 712 | .framesize = 2048, | 712 | .framesize = 2048, |
| 713 | .interval = 3, | 713 | .interval = 1, |
| 714 | } | 714 | } |
| 715 | } | 715 | } |
| 716 | }, | 716 | }, |
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index 2ce3d19c58ef..f10717311e05 100644 --- a/drivers/media/usb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c | |||
| @@ -438,9 +438,9 @@ static int tt3650_rc_query(struct dvb_usb_device *d) | |||
| 438 | 438 | ||
| 439 | if (rx[8] & 0x01) { | 439 | if (rx[8] & 0x01) { |
| 440 | /* got a "press" event */ | 440 | /* got a "press" event */ |
| 441 | st->last_rc_key = (rx[3] << 8) | rx[2]; | 441 | st->last_rc_key = RC_SCANCODE_RC5(rx[3], rx[2]); |
| 442 | deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]); | 442 | deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]); |
| 443 | rc_keydown(d->rc_dev, st->last_rc_key, rx[1]); | 443 | rc_keydown(d->rc_dev, RC_TYPE_RC5, st->last_rc_key, rx[1]); |
| 444 | } else if (st->last_rc_key) { | 444 | } else if (st->last_rc_key) { |
| 445 | rc_keyup(d->rc_dev); | 445 | rc_keyup(d->rc_dev); |
| 446 | st->last_rc_key = 0; | 446 | st->last_rc_key = 0; |
| @@ -747,7 +747,7 @@ static struct dvb_usb_device_properties ttusb2_properties_ct3650 = { | |||
| 747 | .rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */ | 747 | .rc_interval = 150, /* Less than IR_KEYPRESS_TIMEOUT */ |
| 748 | .rc_codes = RC_MAP_TT_1500, | 748 | .rc_codes = RC_MAP_TT_1500, |
| 749 | .rc_query = tt3650_rc_query, | 749 | .rc_query = tt3650_rc_query, |
| 750 | .allowed_protos = RC_BIT_UNKNOWN, | 750 | .allowed_protos = RC_BIT_RC5, |
| 751 | }, | 751 | }, |
| 752 | 752 | ||
| 753 | .num_adapters = 1, | 753 | .num_adapters = 1, |
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 12d4c0326e31..6d2ea9afd57b 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c | |||
| @@ -366,7 +366,7 @@ int em28xx_init_camera(struct em28xx *dev) | |||
| 366 | v4l2->sensor_xtal = 4300000; | 366 | v4l2->sensor_xtal = 4300000; |
| 367 | pdata.xtal = v4l2->sensor_xtal; | 367 | pdata.xtal = v4l2->sensor_xtal; |
| 368 | if (NULL == | 368 | if (NULL == |
| 369 | v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap, | 369 | v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, |
| 370 | &mt9v011_info, NULL)) { | 370 | &mt9v011_info, NULL)) { |
| 371 | ret = -ENODEV; | 371 | ret = -ENODEV; |
| 372 | break; | 372 | break; |
| @@ -423,7 +423,7 @@ int em28xx_init_camera(struct em28xx *dev) | |||
| 423 | v4l2->sensor_yres = 480; | 423 | v4l2->sensor_yres = 480; |
| 424 | 424 | ||
| 425 | subdev = | 425 | subdev = |
| 426 | v4l2_i2c_new_subdev_board(&dev->v4l2->v4l2_dev, adap, | 426 | v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, |
| 427 | &ov2640_info, NULL); | 427 | &ov2640_info, NULL); |
| 428 | if (NULL == subdev) { | 428 | if (NULL == subdev) { |
| 429 | ret = -ENODEV; | 429 | ret = -ENODEV; |
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 15ad47045553..a7e24848f6c8 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c | |||
| @@ -2280,6 +2280,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
| 2280 | .driver_info = EM2820_BOARD_UNKNOWN }, | 2280 | .driver_info = EM2820_BOARD_UNKNOWN }, |
| 2281 | { USB_DEVICE(0xeb1a, 0x2875), | 2281 | { USB_DEVICE(0xeb1a, 0x2875), |
| 2282 | .driver_info = EM2820_BOARD_UNKNOWN }, | 2282 | .driver_info = EM2820_BOARD_UNKNOWN }, |
| 2283 | { USB_DEVICE(0xeb1a, 0x2885), /* MSI Digivox Trio */ | ||
| 2284 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, | ||
| 2283 | { USB_DEVICE(0xeb1a, 0xe300), | 2285 | { USB_DEVICE(0xeb1a, 0xe300), |
| 2284 | .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, | 2286 | .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, |
| 2285 | { USB_DEVICE(0xeb1a, 0xe303), | 2287 | { USB_DEVICE(0xeb1a, 0xe303), |
| @@ -3522,7 +3524,6 @@ static struct usb_driver em28xx_usb_driver = { | |||
| 3522 | .disconnect = em28xx_usb_disconnect, | 3524 | .disconnect = em28xx_usb_disconnect, |
| 3523 | .suspend = em28xx_usb_suspend, | 3525 | .suspend = em28xx_usb_suspend, |
| 3524 | .resume = em28xx_usb_resume, | 3526 | .resume = em28xx_usb_resume, |
| 3525 | .reset_resume = em28xx_usb_resume, | ||
| 3526 | .id_table = em28xx_id_table, | 3527 | .id_table = em28xx_id_table, |
| 3527 | }; | 3528 | }; |
| 3528 | 3529 | ||
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index a121ed9561fd..3a3e243edf89 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c | |||
| @@ -1213,9 +1213,17 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
| 1213 | dvb->fe[0] = dvb_attach(lgdt3305_attach, | 1213 | dvb->fe[0] = dvb_attach(lgdt3305_attach, |
| 1214 | &em2870_lgdt3304_dev, | 1214 | &em2870_lgdt3304_dev, |
| 1215 | &dev->i2c_adap[dev->def_i2c_bus]); | 1215 | &dev->i2c_adap[dev->def_i2c_bus]); |
| 1216 | if (dvb->fe[0] != NULL) | 1216 | if (!dvb->fe[0]) { |
| 1217 | dvb_attach(tda18271_attach, dvb->fe[0], 0x60, | 1217 | result = -EINVAL; |
| 1218 | &dev->i2c_adap[dev->def_i2c_bus], &kworld_a340_config); | 1218 | goto out_free; |
| 1219 | } | ||
| 1220 | if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, | ||
| 1221 | &dev->i2c_adap[dev->def_i2c_bus], | ||
| 1222 | &kworld_a340_config)) { | ||
| 1223 | dvb_frontend_detach(dvb->fe[0]); | ||
| 1224 | result = -EINVAL; | ||
| 1225 | goto out_free; | ||
| 1226 | } | ||
| 1219 | break; | 1227 | break; |
| 1220 | case EM28174_BOARD_PCTV_290E: | 1228 | case EM28174_BOARD_PCTV_290E: |
| 1221 | /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ | 1229 | /* set default GPIO0 for LNA, used if GPIOLIB is undefined */ |
| @@ -1545,6 +1553,7 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
| 1545 | dvb->i2c_client_demod = client; | 1553 | dvb->i2c_client_demod = client; |
| 1546 | 1554 | ||
| 1547 | /* attach tuner */ | 1555 | /* attach tuner */ |
| 1556 | memset(&si2157_config, 0, sizeof(si2157_config)); | ||
| 1548 | si2157_config.fe = dvb->fe[0]; | 1557 | si2157_config.fe = dvb->fe[0]; |
| 1549 | memset(&info, 0, sizeof(struct i2c_board_info)); | 1558 | memset(&info, 0, sizeof(struct i2c_board_info)); |
| 1550 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); | 1559 | strlcpy(info.type, "si2157", I2C_NAME_SIZE); |
| @@ -1645,10 +1654,14 @@ static int em28xx_dvb_fini(struct em28xx *dev) | |||
| 1645 | if (dev->disconnected) { | 1654 | if (dev->disconnected) { |
| 1646 | /* We cannot tell the device to sleep | 1655 | /* We cannot tell the device to sleep |
| 1647 | * once it has been unplugged. */ | 1656 | * once it has been unplugged. */ |
| 1648 | if (dvb->fe[0]) | 1657 | if (dvb->fe[0]) { |
| 1649 | prevent_sleep(&dvb->fe[0]->ops); | 1658 | prevent_sleep(&dvb->fe[0]->ops); |
| 1650 | if (dvb->fe[1]) | 1659 | dvb->fe[0]->exit = DVB_FE_DEVICE_REMOVED; |
| 1660 | } | ||
| 1661 | if (dvb->fe[1]) { | ||
| 1651 | prevent_sleep(&dvb->fe[1]->ops); | 1662 | prevent_sleep(&dvb->fe[1]->ops); |
| 1663 | dvb->fe[1]->exit = DVB_FE_DEVICE_REMOVED; | ||
| 1664 | } | ||
| 1652 | } | 1665 | } |
| 1653 | 1666 | ||
| 1654 | /* remove I2C tuner */ | 1667 | /* remove I2C tuner */ |
| @@ -1712,7 +1725,6 @@ static int em28xx_dvb_resume(struct em28xx *dev) | |||
| 1712 | em28xx_info("Resuming DVB extension"); | 1725 | em28xx_info("Resuming DVB extension"); |
| 1713 | if (dev->dvb) { | 1726 | if (dev->dvb) { |
| 1714 | struct em28xx_dvb *dvb = dev->dvb; | 1727 | struct em28xx_dvb *dvb = dev->dvb; |
| 1715 | struct i2c_client *client = dvb->i2c_client_tuner; | ||
| 1716 | 1728 | ||
| 1717 | if (dvb->fe[0]) { | 1729 | if (dvb->fe[0]) { |
| 1718 | ret = dvb_frontend_resume(dvb->fe[0]); | 1730 | ret = dvb_frontend_resume(dvb->fe[0]); |
| @@ -1723,22 +1735,6 @@ static int em28xx_dvb_resume(struct em28xx *dev) | |||
| 1723 | ret = dvb_frontend_resume(dvb->fe[1]); | 1735 | ret = dvb_frontend_resume(dvb->fe[1]); |
| 1724 | em28xx_info("fe1 resume %d", ret); | 1736 | em28xx_info("fe1 resume %d", ret); |
| 1725 | } | 1737 | } |
| 1726 | /* remove I2C tuner */ | ||
| 1727 | if (client) { | ||
| 1728 | module_put(client->dev.driver->owner); | ||
| 1729 | i2c_unregister_device(client); | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | /* remove I2C demod */ | ||
| 1733 | client = dvb->i2c_client_demod; | ||
| 1734 | if (client) { | ||
| 1735 | module_put(client->dev.driver->owner); | ||
| 1736 | i2c_unregister_device(client); | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | em28xx_unregister_dvb(dvb); | ||
| 1740 | kfree(dvb); | ||
| 1741 | dev->dvb = NULL; | ||
| 1742 | } | 1738 | } |
| 1743 | 1739 | ||
| 1744 | return 0; | 1740 | return 0; |
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index b58d4ebf6419..1048c1a23fb6 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c | |||
| @@ -501,6 +501,12 @@ static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
| 501 | int addr, rc, i; | 501 | int addr, rc, i; |
| 502 | u8 reg; | 502 | u8 reg; |
| 503 | 503 | ||
| 504 | /* prevent i2c xfer attempts after device is disconnected | ||
| 505 | some fe's try to do i2c writes/reads from their release | ||
| 506 | interfaces when called in disconnect path */ | ||
| 507 | if (dev->disconnected) | ||
| 508 | return -ENODEV; | ||
| 509 | |||
| 504 | rc = rt_mutex_trylock(&dev->i2c_bus_lock); | 510 | rc = rt_mutex_trylock(&dev->i2c_bus_lock); |
| 505 | if (rc < 0) | 511 | if (rc < 0) |
| 506 | return rc; | 512 | return rc; |
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 56ef49df4f8d..ed843bd221ea 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/bitrev.h> | ||
| 30 | 31 | ||
| 31 | #include "em28xx.h" | 32 | #include "em28xx.h" |
| 32 | 33 | ||
| @@ -53,6 +54,7 @@ struct em28xx_ir_poll_result { | |||
| 53 | unsigned int toggle_bit:1; | 54 | unsigned int toggle_bit:1; |
| 54 | unsigned int read_count:7; | 55 | unsigned int read_count:7; |
| 55 | 56 | ||
| 57 | enum rc_type protocol; | ||
| 56 | u32 scancode; | 58 | u32 scancode; |
| 57 | }; | 59 | }; |
| 58 | 60 | ||
| @@ -72,7 +74,7 @@ struct em28xx_IR { | |||
| 72 | /* i2c slave address of external device (if used) */ | 74 | /* i2c slave address of external device (if used) */ |
| 73 | u16 i2c_dev_addr; | 75 | u16 i2c_dev_addr; |
| 74 | 76 | ||
| 75 | int (*get_key_i2c)(struct i2c_client *, u32 *); | 77 | int (*get_key_i2c)(struct i2c_client *ir, enum rc_type *protocol, u32 *scancode); |
| 76 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); | 78 | int (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *); |
| 77 | }; | 79 | }; |
| 78 | 80 | ||
| @@ -80,7 +82,8 @@ struct em28xx_IR { | |||
| 80 | I2C IR based get keycodes - should be used with ir-kbd-i2c | 82 | I2C IR based get keycodes - should be used with ir-kbd-i2c |
| 81 | **********************************************************/ | 83 | **********************************************************/ |
| 82 | 84 | ||
| 83 | static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, u32 *ir_key) | 85 | static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, |
| 86 | enum rc_type *protocol, u32 *scancode) | ||
| 84 | { | 87 | { |
| 85 | unsigned char b; | 88 | unsigned char b; |
| 86 | 89 | ||
| @@ -98,14 +101,15 @@ static int em28xx_get_key_terratec(struct i2c_client *i2c_dev, u32 *ir_key) | |||
| 98 | /* keep old data */ | 101 | /* keep old data */ |
| 99 | return 1; | 102 | return 1; |
| 100 | 103 | ||
| 101 | *ir_key = b; | 104 | *protocol = RC_TYPE_UNKNOWN; |
| 105 | *scancode = b; | ||
| 102 | return 1; | 106 | return 1; |
| 103 | } | 107 | } |
| 104 | 108 | ||
| 105 | static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev, u32 *ir_key) | 109 | static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev, |
| 110 | enum rc_type *protocol, u32 *scancode) | ||
| 106 | { | 111 | { |
| 107 | unsigned char buf[2]; | 112 | unsigned char buf[2]; |
| 108 | u16 code; | ||
| 109 | int size; | 113 | int size; |
| 110 | 114 | ||
| 111 | /* poll IR chip */ | 115 | /* poll IR chip */ |
| @@ -127,26 +131,13 @@ static int em28xx_get_key_em_haup(struct i2c_client *i2c_dev, u32 *ir_key) | |||
| 127 | * So, the code translation is not complete. Yet, it is enough to | 131 | * So, the code translation is not complete. Yet, it is enough to |
| 128 | * work with the provided RC5 IR. | 132 | * work with the provided RC5 IR. |
| 129 | */ | 133 | */ |
| 130 | code = | 134 | *protocol = RC_TYPE_RC5; |
| 131 | ((buf[0] & 0x01) ? 0x0020 : 0) | /* 0010 0000 */ | 135 | *scancode = (bitrev8(buf[1]) & 0x1f) << 8 | bitrev8(buf[0]) >> 2; |
| 132 | ((buf[0] & 0x02) ? 0x0010 : 0) | /* 0001 0000 */ | ||
| 133 | ((buf[0] & 0x04) ? 0x0008 : 0) | /* 0000 1000 */ | ||
| 134 | ((buf[0] & 0x08) ? 0x0004 : 0) | /* 0000 0100 */ | ||
| 135 | ((buf[0] & 0x10) ? 0x0002 : 0) | /* 0000 0010 */ | ||
| 136 | ((buf[0] & 0x20) ? 0x0001 : 0) | /* 0000 0001 */ | ||
| 137 | ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000 */ | ||
| 138 | ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000 */ | ||
| 139 | ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100 */ | ||
| 140 | ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010 */ | ||
| 141 | ((buf[1] & 0x80) ? 0x0100 : 0); /* 0000 0001 */ | ||
| 142 | |||
| 143 | /* return key */ | ||
| 144 | *ir_key = code; | ||
| 145 | return 1; | 136 | return 1; |
| 146 | } | 137 | } |
| 147 | 138 | ||
| 148 | static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev, | 139 | static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev, |
| 149 | u32 *ir_key) | 140 | enum rc_type *protocol, u32 *scancode) |
| 150 | { | 141 | { |
| 151 | unsigned char buf[3]; | 142 | unsigned char buf[3]; |
| 152 | 143 | ||
| @@ -158,13 +149,13 @@ static int em28xx_get_key_pinnacle_usb_grey(struct i2c_client *i2c_dev, | |||
| 158 | if (buf[0] != 0x00) | 149 | if (buf[0] != 0x00) |
| 159 | return 0; | 150 | return 0; |
| 160 | 151 | ||
| 161 | *ir_key = buf[2]&0x3f; | 152 | *protocol = RC_TYPE_UNKNOWN; |
| 162 | 153 | *scancode = buf[2] & 0x3f; | |
| 163 | return 1; | 154 | return 1; |
| 164 | } | 155 | } |
| 165 | 156 | ||
| 166 | static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev, | 157 | static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev, |
| 167 | u32 *ir_key) | 158 | enum rc_type *protocol, u32 *scancode) |
| 168 | { | 159 | { |
| 169 | unsigned char subaddr, keydetect, key; | 160 | unsigned char subaddr, keydetect, key; |
| 170 | 161 | ||
| @@ -184,7 +175,8 @@ static int em28xx_get_key_winfast_usbii_deluxe(struct i2c_client *i2c_dev, | |||
| 184 | if (key == 0x00) | 175 | if (key == 0x00) |
| 185 | return 0; | 176 | return 0; |
| 186 | 177 | ||
| 187 | *ir_key = key; | 178 | *protocol = RC_TYPE_UNKNOWN; |
| 179 | *scancode = key; | ||
| 188 | return 1; | 180 | return 1; |
| 189 | } | 181 | } |
| 190 | 182 | ||
| @@ -215,7 +207,22 @@ static int default_polling_getkey(struct em28xx_IR *ir, | |||
| 215 | poll_result->read_count = (msg[0] & 0x7f); | 207 | poll_result->read_count = (msg[0] & 0x7f); |
| 216 | 208 | ||
| 217 | /* Remote Control Address/Data (Regs 0x46/0x47) */ | 209 | /* Remote Control Address/Data (Regs 0x46/0x47) */ |
| 218 | poll_result->scancode = msg[1] << 8 | msg[2]; | 210 | switch (ir->rc_type) { |
| 211 | case RC_BIT_RC5: | ||
| 212 | poll_result->protocol = RC_TYPE_RC5; | ||
| 213 | poll_result->scancode = RC_SCANCODE_RC5(msg[1], msg[2]); | ||
| 214 | break; | ||
| 215 | |||
| 216 | case RC_BIT_NEC: | ||
| 217 | poll_result->protocol = RC_TYPE_NEC; | ||
| 218 | poll_result->scancode = RC_SCANCODE_NEC(msg[1], msg[2]); | ||
| 219 | break; | ||
| 220 | |||
| 221 | default: | ||
| 222 | poll_result->protocol = RC_TYPE_UNKNOWN; | ||
| 223 | poll_result->scancode = msg[1] << 8 | msg[2]; | ||
| 224 | break; | ||
| 225 | } | ||
| 219 | 226 | ||
| 220 | return 0; | 227 | return 0; |
| 221 | } | 228 | } |
| @@ -247,25 +254,32 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, | |||
| 247 | */ | 254 | */ |
| 248 | switch (ir->rc_type) { | 255 | switch (ir->rc_type) { |
| 249 | case RC_BIT_RC5: | 256 | case RC_BIT_RC5: |
| 250 | poll_result->scancode = msg[1] << 8 | msg[2]; | 257 | poll_result->protocol = RC_TYPE_RC5; |
| 258 | poll_result->scancode = RC_SCANCODE_RC5(msg[1], msg[2]); | ||
| 251 | break; | 259 | break; |
| 260 | |||
| 252 | case RC_BIT_NEC: | 261 | case RC_BIT_NEC: |
| 262 | poll_result->protocol = RC_TYPE_RC5; | ||
| 263 | poll_result->scancode = msg[1] << 8 | msg[2]; | ||
| 253 | if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */ | 264 | if ((msg[3] ^ msg[4]) != 0xff) /* 32 bits NEC */ |
| 254 | poll_result->scancode = (msg[1] << 24) | | 265 | poll_result->scancode = RC_SCANCODE_NEC32((msg[1] << 24) | |
| 255 | (msg[2] << 16) | | 266 | (msg[2] << 16) | |
| 256 | (msg[3] << 8) | | 267 | (msg[3] << 8) | |
| 257 | msg[4]; | 268 | (msg[4])); |
| 258 | else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */ | 269 | else if ((msg[1] ^ msg[2]) != 0xff) /* 24 bits NEC */ |
| 259 | poll_result->scancode = (msg[1] << 16) | | 270 | poll_result->scancode = RC_SCANCODE_NECX(msg[1] << 8 | |
| 260 | (msg[2] << 8) | | 271 | msg[2], msg[3]); |
| 261 | msg[3]; | ||
| 262 | else /* Normal NEC */ | 272 | else /* Normal NEC */ |
| 263 | poll_result->scancode = msg[1] << 8 | msg[3]; | 273 | poll_result->scancode = RC_SCANCODE_NEC(msg[1], msg[3]); |
| 264 | break; | 274 | break; |
| 275 | |||
| 265 | case RC_BIT_RC6_0: | 276 | case RC_BIT_RC6_0: |
| 266 | poll_result->scancode = msg[1] << 8 | msg[2]; | 277 | poll_result->protocol = RC_TYPE_RC6_0; |
| 278 | poll_result->scancode = RC_SCANCODE_RC6_0(msg[1], msg[2]); | ||
| 267 | break; | 279 | break; |
| 280 | |||
| 268 | default: | 281 | default: |
| 282 | poll_result->protocol = RC_TYPE_UNKNOWN; | ||
| 269 | poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | | 283 | poll_result->scancode = (msg[1] << 24) | (msg[2] << 16) | |
| 270 | (msg[3] << 8) | msg[4]; | 284 | (msg[3] << 8) | msg[4]; |
| 271 | break; | 285 | break; |
| @@ -281,22 +295,24 @@ static int em2874_polling_getkey(struct em28xx_IR *ir, | |||
| 281 | static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir) | 295 | static int em28xx_i2c_ir_handle_key(struct em28xx_IR *ir) |
| 282 | { | 296 | { |
| 283 | struct em28xx *dev = ir->dev; | 297 | struct em28xx *dev = ir->dev; |
| 284 | static u32 ir_key; | 298 | static u32 scancode; |
| 299 | enum rc_type protocol; | ||
| 285 | int rc; | 300 | int rc; |
| 286 | struct i2c_client client; | 301 | struct i2c_client client; |
| 287 | 302 | ||
| 288 | client.adapter = &ir->dev->i2c_adap[dev->def_i2c_bus]; | 303 | client.adapter = &ir->dev->i2c_adap[dev->def_i2c_bus]; |
| 289 | client.addr = ir->i2c_dev_addr; | 304 | client.addr = ir->i2c_dev_addr; |
| 290 | 305 | ||
| 291 | rc = ir->get_key_i2c(&client, &ir_key); | 306 | rc = ir->get_key_i2c(&client, &protocol, &scancode); |
| 292 | if (rc < 0) { | 307 | if (rc < 0) { |
| 293 | dprintk("ir->get_key_i2c() failed: %d\n", rc); | 308 | dprintk("ir->get_key_i2c() failed: %d\n", rc); |
| 294 | return rc; | 309 | return rc; |
| 295 | } | 310 | } |
| 296 | 311 | ||
| 297 | if (rc) { | 312 | if (rc) { |
| 298 | dprintk("%s: keycode = 0x%04x\n", __func__, ir_key); | 313 | dprintk("%s: proto = 0x%04x, scancode = 0x%04x\n", |
| 299 | rc_keydown(ir->rc, ir_key, 0); | 314 | __func__, protocol, scancode); |
| 315 | rc_keydown(ir->rc, protocol, scancode, 0); | ||
| 300 | } | 316 | } |
| 301 | return 0; | 317 | return 0; |
| 302 | } | 318 | } |
| @@ -319,10 +335,12 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) | |||
| 319 | poll_result.scancode); | 335 | poll_result.scancode); |
| 320 | if (ir->full_code) | 336 | if (ir->full_code) |
| 321 | rc_keydown(ir->rc, | 337 | rc_keydown(ir->rc, |
| 338 | poll_result.protocol, | ||
| 322 | poll_result.scancode, | 339 | poll_result.scancode, |
| 323 | poll_result.toggle_bit); | 340 | poll_result.toggle_bit); |
| 324 | else | 341 | else |
| 325 | rc_keydown(ir->rc, | 342 | rc_keydown(ir->rc, |
| 343 | RC_TYPE_UNKNOWN, | ||
| 326 | poll_result.scancode & 0xff, | 344 | poll_result.scancode & 0xff, |
| 327 | poll_result.toggle_bit); | 345 | poll_result.toggle_bit); |
| 328 | 346 | ||
| @@ -727,7 +745,7 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
| 727 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: | 745 | case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: |
| 728 | rc->map_name = RC_MAP_HAUPPAUGE; | 746 | rc->map_name = RC_MAP_HAUPPAUGE; |
| 729 | ir->get_key_i2c = em28xx_get_key_em_haup; | 747 | ir->get_key_i2c = em28xx_get_key_em_haup; |
| 730 | rc_set_allowed_protocols(rc, RC_BIT_RC5); | 748 | rc->allowed_protocols = RC_BIT_RC5; |
| 731 | break; | 749 | break; |
| 732 | case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: | 750 | case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: |
| 733 | rc->map_name = RC_MAP_WINFAST_USBII_DELUXE; | 751 | rc->map_name = RC_MAP_WINFAST_USBII_DELUXE; |
| @@ -743,7 +761,7 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
| 743 | switch (dev->chip_id) { | 761 | switch (dev->chip_id) { |
| 744 | case CHIP_ID_EM2860: | 762 | case CHIP_ID_EM2860: |
| 745 | case CHIP_ID_EM2883: | 763 | case CHIP_ID_EM2883: |
| 746 | rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); | 764 | rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC; |
| 747 | ir->get_key = default_polling_getkey; | 765 | ir->get_key = default_polling_getkey; |
| 748 | break; | 766 | break; |
| 749 | case CHIP_ID_EM2884: | 767 | case CHIP_ID_EM2884: |
| @@ -751,8 +769,8 @@ static int em28xx_ir_init(struct em28xx *dev) | |||
| 751 | case CHIP_ID_EM28174: | 769 | case CHIP_ID_EM28174: |
| 752 | case CHIP_ID_EM28178: | 770 | case CHIP_ID_EM28178: |
| 753 | ir->get_key = em2874_polling_getkey; | 771 | ir->get_key = em2874_polling_getkey; |
| 754 | rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC | | 772 | rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC | |
| 755 | RC_BIT_RC6_0); | 773 | RC_BIT_RC6_0; |
| 756 | break; | 774 | break; |
| 757 | default: | 775 | default: |
| 758 | err = -ENODEV; | 776 | err = -ENODEV; |
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index f6b49c98e2c9..90dec2955f1c 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c | |||
| @@ -1227,8 +1227,7 @@ static void scale_to_size(struct em28xx *dev, | |||
| 1227 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 1227 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
| 1228 | struct v4l2_format *f) | 1228 | struct v4l2_format *f) |
| 1229 | { | 1229 | { |
| 1230 | struct em28xx_fh *fh = priv; | 1230 | struct em28xx *dev = video_drvdata(file); |
| 1231 | struct em28xx *dev = fh->dev; | ||
| 1232 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1231 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1233 | 1232 | ||
| 1234 | f->fmt.pix.width = v4l2->width; | 1233 | f->fmt.pix.width = v4l2->width; |
| @@ -1261,8 +1260,7 @@ static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc) | |||
| 1261 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 1260 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
| 1262 | struct v4l2_format *f) | 1261 | struct v4l2_format *f) |
| 1263 | { | 1262 | { |
| 1264 | struct em28xx_fh *fh = priv; | 1263 | struct em28xx *dev = video_drvdata(file); |
| 1265 | struct em28xx *dev = fh->dev; | ||
| 1266 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1264 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1267 | unsigned int width = f->fmt.pix.width; | 1265 | unsigned int width = f->fmt.pix.width; |
| 1268 | unsigned int height = f->fmt.pix.height; | 1266 | unsigned int height = f->fmt.pix.height; |
| @@ -1355,8 +1353,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 1355 | 1353 | ||
| 1356 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) | 1354 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) |
| 1357 | { | 1355 | { |
| 1358 | struct em28xx_fh *fh = priv; | 1356 | struct em28xx *dev = video_drvdata(file); |
| 1359 | struct em28xx *dev = fh->dev; | ||
| 1360 | 1357 | ||
| 1361 | *norm = dev->v4l2->norm; | 1358 | *norm = dev->v4l2->norm; |
| 1362 | 1359 | ||
| @@ -1365,8 +1362,7 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm) | |||
| 1365 | 1362 | ||
| 1366 | static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) | 1363 | static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) |
| 1367 | { | 1364 | { |
| 1368 | struct em28xx_fh *fh = priv; | 1365 | struct em28xx *dev = video_drvdata(file); |
| 1369 | struct em28xx *dev = fh->dev; | ||
| 1370 | 1366 | ||
| 1371 | v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm); | 1367 | v4l2_device_call_all(&dev->v4l2->v4l2_dev, 0, video, querystd, norm); |
| 1372 | 1368 | ||
| @@ -1375,8 +1371,7 @@ static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm) | |||
| 1375 | 1371 | ||
| 1376 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) | 1372 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) |
| 1377 | { | 1373 | { |
| 1378 | struct em28xx_fh *fh = priv; | 1374 | struct em28xx *dev = video_drvdata(file); |
| 1379 | struct em28xx *dev = fh->dev; | ||
| 1380 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1375 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1381 | struct v4l2_format f; | 1376 | struct v4l2_format f; |
| 1382 | 1377 | ||
| @@ -1408,8 +1403,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm) | |||
| 1408 | static int vidioc_g_parm(struct file *file, void *priv, | 1403 | static int vidioc_g_parm(struct file *file, void *priv, |
| 1409 | struct v4l2_streamparm *p) | 1404 | struct v4l2_streamparm *p) |
| 1410 | { | 1405 | { |
| 1411 | struct em28xx_fh *fh = priv; | 1406 | struct em28xx *dev = video_drvdata(file); |
| 1412 | struct em28xx *dev = fh->dev; | ||
| 1413 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1407 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1414 | int rc = 0; | 1408 | int rc = 0; |
| 1415 | 1409 | ||
| @@ -1427,8 +1421,7 @@ static int vidioc_g_parm(struct file *file, void *priv, | |||
| 1427 | static int vidioc_s_parm(struct file *file, void *priv, | 1421 | static int vidioc_s_parm(struct file *file, void *priv, |
| 1428 | struct v4l2_streamparm *p) | 1422 | struct v4l2_streamparm *p) |
| 1429 | { | 1423 | { |
| 1430 | struct em28xx_fh *fh = priv; | 1424 | struct em28xx *dev = video_drvdata(file); |
| 1431 | struct em28xx *dev = fh->dev; | ||
| 1432 | 1425 | ||
| 1433 | p->parm.capture.readbuffers = EM28XX_MIN_BUF; | 1426 | p->parm.capture.readbuffers = EM28XX_MIN_BUF; |
| 1434 | return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, | 1427 | return v4l2_device_call_until_err(&dev->v4l2->v4l2_dev, |
| @@ -1450,8 +1443,7 @@ static const char *iname[] = { | |||
| 1450 | static int vidioc_enum_input(struct file *file, void *priv, | 1443 | static int vidioc_enum_input(struct file *file, void *priv, |
| 1451 | struct v4l2_input *i) | 1444 | struct v4l2_input *i) |
| 1452 | { | 1445 | { |
| 1453 | struct em28xx_fh *fh = priv; | 1446 | struct em28xx *dev = video_drvdata(file); |
| 1454 | struct em28xx *dev = fh->dev; | ||
| 1455 | unsigned int n; | 1447 | unsigned int n; |
| 1456 | 1448 | ||
| 1457 | n = i->index; | 1449 | n = i->index; |
| @@ -1479,8 +1471,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
| 1479 | 1471 | ||
| 1480 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1472 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
| 1481 | { | 1473 | { |
| 1482 | struct em28xx_fh *fh = priv; | 1474 | struct em28xx *dev = video_drvdata(file); |
| 1483 | struct em28xx *dev = fh->dev; | ||
| 1484 | 1475 | ||
| 1485 | *i = dev->ctl_input; | 1476 | *i = dev->ctl_input; |
| 1486 | 1477 | ||
| @@ -1489,8 +1480,7 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | |||
| 1489 | 1480 | ||
| 1490 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1481 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) |
| 1491 | { | 1482 | { |
| 1492 | struct em28xx_fh *fh = priv; | 1483 | struct em28xx *dev = video_drvdata(file); |
| 1493 | struct em28xx *dev = fh->dev; | ||
| 1494 | 1484 | ||
| 1495 | if (i >= MAX_EM28XX_INPUT) | 1485 | if (i >= MAX_EM28XX_INPUT) |
| 1496 | return -EINVAL; | 1486 | return -EINVAL; |
| @@ -1503,8 +1493,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
| 1503 | 1493 | ||
| 1504 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | 1494 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) |
| 1505 | { | 1495 | { |
| 1506 | struct em28xx_fh *fh = priv; | 1496 | struct em28xx *dev = video_drvdata(file); |
| 1507 | struct em28xx *dev = fh->dev; | ||
| 1508 | 1497 | ||
| 1509 | switch (a->index) { | 1498 | switch (a->index) { |
| 1510 | case EM28XX_AMUX_VIDEO: | 1499 | case EM28XX_AMUX_VIDEO: |
| @@ -1543,8 +1532,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | |||
| 1543 | 1532 | ||
| 1544 | static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) | 1533 | static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a) |
| 1545 | { | 1534 | { |
| 1546 | struct em28xx_fh *fh = priv; | 1535 | struct em28xx *dev = video_drvdata(file); |
| 1547 | struct em28xx *dev = fh->dev; | ||
| 1548 | 1536 | ||
| 1549 | if (a->index >= MAX_EM28XX_INPUT) | 1537 | if (a->index >= MAX_EM28XX_INPUT) |
| 1550 | return -EINVAL; | 1538 | return -EINVAL; |
| @@ -1563,8 +1551,7 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio | |||
| 1563 | static int vidioc_g_tuner(struct file *file, void *priv, | 1551 | static int vidioc_g_tuner(struct file *file, void *priv, |
| 1564 | struct v4l2_tuner *t) | 1552 | struct v4l2_tuner *t) |
| 1565 | { | 1553 | { |
| 1566 | struct em28xx_fh *fh = priv; | 1554 | struct em28xx *dev = video_drvdata(file); |
| 1567 | struct em28xx *dev = fh->dev; | ||
| 1568 | 1555 | ||
| 1569 | if (0 != t->index) | 1556 | if (0 != t->index) |
| 1570 | return -EINVAL; | 1557 | return -EINVAL; |
| @@ -1578,8 +1565,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, | |||
| 1578 | static int vidioc_s_tuner(struct file *file, void *priv, | 1565 | static int vidioc_s_tuner(struct file *file, void *priv, |
| 1579 | const struct v4l2_tuner *t) | 1566 | const struct v4l2_tuner *t) |
| 1580 | { | 1567 | { |
| 1581 | struct em28xx_fh *fh = priv; | 1568 | struct em28xx *dev = video_drvdata(file); |
| 1582 | struct em28xx *dev = fh->dev; | ||
| 1583 | 1569 | ||
| 1584 | if (0 != t->index) | 1570 | if (0 != t->index) |
| 1585 | return -EINVAL; | 1571 | return -EINVAL; |
| @@ -1591,8 +1577,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, | |||
| 1591 | static int vidioc_g_frequency(struct file *file, void *priv, | 1577 | static int vidioc_g_frequency(struct file *file, void *priv, |
| 1592 | struct v4l2_frequency *f) | 1578 | struct v4l2_frequency *f) |
| 1593 | { | 1579 | { |
| 1594 | struct em28xx_fh *fh = priv; | 1580 | struct em28xx *dev = video_drvdata(file); |
| 1595 | struct em28xx *dev = fh->dev; | ||
| 1596 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1581 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1597 | 1582 | ||
| 1598 | if (0 != f->tuner) | 1583 | if (0 != f->tuner) |
| @@ -1606,8 +1591,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 1606 | const struct v4l2_frequency *f) | 1591 | const struct v4l2_frequency *f) |
| 1607 | { | 1592 | { |
| 1608 | struct v4l2_frequency new_freq = *f; | 1593 | struct v4l2_frequency new_freq = *f; |
| 1609 | struct em28xx_fh *fh = priv; | 1594 | struct em28xx *dev = video_drvdata(file); |
| 1610 | struct em28xx *dev = fh->dev; | ||
| 1611 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1595 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1612 | 1596 | ||
| 1613 | if (0 != f->tuner) | 1597 | if (0 != f->tuner) |
| @@ -1624,8 +1608,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
| 1624 | static int vidioc_g_chip_info(struct file *file, void *priv, | 1608 | static int vidioc_g_chip_info(struct file *file, void *priv, |
| 1625 | struct v4l2_dbg_chip_info *chip) | 1609 | struct v4l2_dbg_chip_info *chip) |
| 1626 | { | 1610 | { |
| 1627 | struct em28xx_fh *fh = priv; | 1611 | struct em28xx *dev = video_drvdata(file); |
| 1628 | struct em28xx *dev = fh->dev; | ||
| 1629 | 1612 | ||
| 1630 | if (chip->match.addr > 1) | 1613 | if (chip->match.addr > 1) |
| 1631 | return -EINVAL; | 1614 | return -EINVAL; |
| @@ -1652,8 +1635,7 @@ static int em28xx_reg_len(int reg) | |||
| 1652 | static int vidioc_g_register(struct file *file, void *priv, | 1635 | static int vidioc_g_register(struct file *file, void *priv, |
| 1653 | struct v4l2_dbg_register *reg) | 1636 | struct v4l2_dbg_register *reg) |
| 1654 | { | 1637 | { |
| 1655 | struct em28xx_fh *fh = priv; | 1638 | struct em28xx *dev = video_drvdata(file); |
| 1656 | struct em28xx *dev = fh->dev; | ||
| 1657 | int ret; | 1639 | int ret; |
| 1658 | 1640 | ||
| 1659 | if (reg->match.addr > 1) | 1641 | if (reg->match.addr > 1) |
| @@ -1693,8 +1675,7 @@ static int vidioc_g_register(struct file *file, void *priv, | |||
| 1693 | static int vidioc_s_register(struct file *file, void *priv, | 1675 | static int vidioc_s_register(struct file *file, void *priv, |
| 1694 | const struct v4l2_dbg_register *reg) | 1676 | const struct v4l2_dbg_register *reg) |
| 1695 | { | 1677 | { |
| 1696 | struct em28xx_fh *fh = priv; | 1678 | struct em28xx *dev = video_drvdata(file); |
| 1697 | struct em28xx *dev = fh->dev; | ||
| 1698 | __le16 buf; | 1679 | __le16 buf; |
| 1699 | 1680 | ||
| 1700 | if (reg->match.addr > 1) | 1681 | if (reg->match.addr > 1) |
| @@ -1715,8 +1696,7 @@ static int vidioc_querycap(struct file *file, void *priv, | |||
| 1715 | struct v4l2_capability *cap) | 1696 | struct v4l2_capability *cap) |
| 1716 | { | 1697 | { |
| 1717 | struct video_device *vdev = video_devdata(file); | 1698 | struct video_device *vdev = video_devdata(file); |
| 1718 | struct em28xx_fh *fh = priv; | 1699 | struct em28xx *dev = video_drvdata(file); |
| 1719 | struct em28xx *dev = fh->dev; | ||
| 1720 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1700 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1721 | 1701 | ||
| 1722 | strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); | 1702 | strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); |
| @@ -1761,8 +1741,7 @@ static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | |||
| 1761 | static int vidioc_enum_framesizes(struct file *file, void *priv, | 1741 | static int vidioc_enum_framesizes(struct file *file, void *priv, |
| 1762 | struct v4l2_frmsizeenum *fsize) | 1742 | struct v4l2_frmsizeenum *fsize) |
| 1763 | { | 1743 | { |
| 1764 | struct em28xx_fh *fh = priv; | 1744 | struct em28xx *dev = video_drvdata(file); |
| 1765 | struct em28xx *dev = fh->dev; | ||
| 1766 | struct em28xx_fmt *fmt; | 1745 | struct em28xx_fmt *fmt; |
| 1767 | unsigned int maxw = norm_maxw(dev); | 1746 | unsigned int maxw = norm_maxw(dev); |
| 1768 | unsigned int maxh = norm_maxh(dev); | 1747 | unsigned int maxh = norm_maxh(dev); |
| @@ -1806,8 +1785,7 @@ static int vidioc_enum_framesizes(struct file *file, void *priv, | |||
| 1806 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | 1785 | static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, |
| 1807 | struct v4l2_format *format) | 1786 | struct v4l2_format *format) |
| 1808 | { | 1787 | { |
| 1809 | struct em28xx_fh *fh = priv; | 1788 | struct em28xx *dev = video_drvdata(file); |
| 1810 | struct em28xx *dev = fh->dev; | ||
| 1811 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1789 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1812 | 1790 | ||
| 1813 | format->fmt.vbi.samples_per_line = v4l2->vbi_width; | 1791 | format->fmt.vbi.samples_per_line = v4l2->vbi_width; |
| @@ -1840,7 +1818,7 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv, | |||
| 1840 | static int radio_g_tuner(struct file *file, void *priv, | 1818 | static int radio_g_tuner(struct file *file, void *priv, |
| 1841 | struct v4l2_tuner *t) | 1819 | struct v4l2_tuner *t) |
| 1842 | { | 1820 | { |
| 1843 | struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; | 1821 | struct em28xx *dev = video_drvdata(file); |
| 1844 | 1822 | ||
| 1845 | if (unlikely(t->index > 0)) | 1823 | if (unlikely(t->index > 0)) |
| 1846 | return -EINVAL; | 1824 | return -EINVAL; |
| @@ -1855,7 +1833,7 @@ static int radio_g_tuner(struct file *file, void *priv, | |||
| 1855 | static int radio_s_tuner(struct file *file, void *priv, | 1833 | static int radio_s_tuner(struct file *file, void *priv, |
| 1856 | const struct v4l2_tuner *t) | 1834 | const struct v4l2_tuner *t) |
| 1857 | { | 1835 | { |
| 1858 | struct em28xx *dev = ((struct em28xx_fh *)priv)->dev; | 1836 | struct em28xx *dev = video_drvdata(file); |
| 1859 | 1837 | ||
| 1860 | if (0 != t->index) | 1838 | if (0 != t->index) |
| 1861 | return -EINVAL; | 1839 | return -EINVAL; |
| @@ -1890,7 +1868,7 @@ static int em28xx_v4l2_open(struct file *filp) | |||
| 1890 | struct em28xx *dev = video_drvdata(filp); | 1868 | struct em28xx *dev = video_drvdata(filp); |
| 1891 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 1869 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 1892 | enum v4l2_buf_type fh_type = 0; | 1870 | enum v4l2_buf_type fh_type = 0; |
| 1893 | struct em28xx_fh *fh; | 1871 | int ret; |
| 1894 | 1872 | ||
| 1895 | switch (vdev->vfl_type) { | 1873 | switch (vdev->vfl_type) { |
| 1896 | case VFL_TYPE_GRABBER: | 1874 | case VFL_TYPE_GRABBER: |
| @@ -1905,24 +1883,23 @@ static int em28xx_v4l2_open(struct file *filp) | |||
| 1905 | return -EINVAL; | 1883 | return -EINVAL; |
| 1906 | } | 1884 | } |
| 1907 | 1885 | ||
| 1908 | em28xx_videodbg("open dev=%s type=%s users=%d\n", | 1886 | em28xx_videodbg("open dev=%s type=%s\n", |
| 1909 | video_device_node_name(vdev), v4l2_type_names[fh_type], | 1887 | video_device_node_name(vdev), v4l2_type_names[fh_type]); |
| 1910 | v4l2->users); | ||
| 1911 | 1888 | ||
| 1912 | if (mutex_lock_interruptible(&dev->lock)) | 1889 | if (mutex_lock_interruptible(&dev->lock)) |
| 1913 | return -ERESTARTSYS; | 1890 | return -ERESTARTSYS; |
| 1914 | fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); | 1891 | |
| 1915 | if (!fh) { | 1892 | ret = v4l2_fh_open(filp); |
| 1916 | em28xx_errdev("em28xx-video.c: Out of memory?!\n"); | 1893 | if (ret) { |
| 1894 | em28xx_errdev("%s: v4l2_fh_open() returned error %d\n", | ||
| 1895 | __func__, ret); | ||
| 1917 | mutex_unlock(&dev->lock); | 1896 | mutex_unlock(&dev->lock); |
| 1918 | return -ENOMEM; | 1897 | return ret; |
| 1919 | } | 1898 | } |
| 1920 | v4l2_fh_init(&fh->fh, vdev); | ||
| 1921 | fh->dev = dev; | ||
| 1922 | fh->type = fh_type; | ||
| 1923 | filp->private_data = fh; | ||
| 1924 | 1899 | ||
| 1925 | if (v4l2->users == 0) { | 1900 | if (v4l2_fh_is_singular_file(filp)) { |
| 1901 | em28xx_videodbg("first opened filehandle, initializing device\n"); | ||
| 1902 | |||
| 1926 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | 1903 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); |
| 1927 | 1904 | ||
| 1928 | if (vdev->vfl_type != VFL_TYPE_RADIO) | 1905 | if (vdev->vfl_type != VFL_TYPE_RADIO) |
| @@ -1933,6 +1910,8 @@ static int em28xx_v4l2_open(struct file *filp) | |||
| 1933 | * of some i2c devices | 1910 | * of some i2c devices |
| 1934 | */ | 1911 | */ |
| 1935 | em28xx_wake_i2c(dev); | 1912 | em28xx_wake_i2c(dev); |
| 1913 | } else { | ||
| 1914 | em28xx_videodbg("further filehandles are already opened\n"); | ||
| 1936 | } | 1915 | } |
| 1937 | 1916 | ||
| 1938 | if (vdev->vfl_type == VFL_TYPE_RADIO) { | 1917 | if (vdev->vfl_type == VFL_TYPE_RADIO) { |
| @@ -1942,10 +1921,8 @@ static int em28xx_v4l2_open(struct file *filp) | |||
| 1942 | 1921 | ||
| 1943 | kref_get(&dev->ref); | 1922 | kref_get(&dev->ref); |
| 1944 | kref_get(&v4l2->ref); | 1923 | kref_get(&v4l2->ref); |
| 1945 | v4l2->users++; | ||
| 1946 | 1924 | ||
| 1947 | mutex_unlock(&dev->lock); | 1925 | mutex_unlock(&dev->lock); |
| 1948 | v4l2_fh_add(&fh->fh); | ||
| 1949 | 1926 | ||
| 1950 | return 0; | 1927 | return 0; |
| 1951 | } | 1928 | } |
| @@ -2046,17 +2023,15 @@ static int em28xx_v4l2_resume(struct em28xx *dev) | |||
| 2046 | */ | 2023 | */ |
| 2047 | static int em28xx_v4l2_close(struct file *filp) | 2024 | static int em28xx_v4l2_close(struct file *filp) |
| 2048 | { | 2025 | { |
| 2049 | struct em28xx_fh *fh = filp->private_data; | 2026 | struct em28xx *dev = video_drvdata(filp); |
| 2050 | struct em28xx *dev = fh->dev; | ||
| 2051 | struct em28xx_v4l2 *v4l2 = dev->v4l2; | 2027 | struct em28xx_v4l2 *v4l2 = dev->v4l2; |
| 2052 | int errCode; | 2028 | int errCode; |
| 2053 | 2029 | ||
| 2054 | em28xx_videodbg("users=%d\n", v4l2->users); | ||
| 2055 | |||
| 2056 | vb2_fop_release(filp); | ||
| 2057 | mutex_lock(&dev->lock); | 2030 | mutex_lock(&dev->lock); |
| 2058 | 2031 | ||
| 2059 | if (v4l2->users == 1) { | 2032 | if (v4l2_fh_is_singular_file(filp)) { |
| 2033 | em28xx_videodbg("last opened filehandle, shutting down device\n"); | ||
| 2034 | |||
| 2060 | /* No sense to try to write to the device */ | 2035 | /* No sense to try to write to the device */ |
| 2061 | if (dev->disconnected) | 2036 | if (dev->disconnected) |
| 2062 | goto exit; | 2037 | goto exit; |
| @@ -2075,10 +2050,12 @@ static int em28xx_v4l2_close(struct file *filp) | |||
| 2075 | em28xx_errdev("cannot change alternate number to " | 2050 | em28xx_errdev("cannot change alternate number to " |
| 2076 | "0 (error=%i)\n", errCode); | 2051 | "0 (error=%i)\n", errCode); |
| 2077 | } | 2052 | } |
| 2053 | } else { | ||
| 2054 | em28xx_videodbg("further opened filehandles left\n"); | ||
| 2078 | } | 2055 | } |
| 2079 | 2056 | ||
| 2080 | exit: | 2057 | exit: |
| 2081 | v4l2->users--; | 2058 | vb2_fop_release(filp); |
| 2082 | kref_put(&v4l2->ref, em28xx_free_v4l2); | 2059 | kref_put(&v4l2->ref, em28xx_free_v4l2); |
| 2083 | mutex_unlock(&dev->lock); | 2060 | mutex_unlock(&dev->lock); |
| 2084 | kref_put(&dev->ref, em28xx_free_device); | 2061 | kref_put(&dev->ref, em28xx_free_device); |
| @@ -2208,7 +2185,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
| 2208 | vfd->v4l2_dev = &dev->v4l2->v4l2_dev; | 2185 | vfd->v4l2_dev = &dev->v4l2->v4l2_dev; |
| 2209 | vfd->debug = video_debug; | 2186 | vfd->debug = video_debug; |
| 2210 | vfd->lock = &dev->lock; | 2187 | vfd->lock = &dev->lock; |
| 2211 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
| 2212 | if (dev->board.is_webcam) | 2188 | if (dev->board.is_webcam) |
| 2213 | vfd->tvnorms = 0; | 2189 | vfd->tvnorms = 0; |
| 2214 | 2190 | ||
| @@ -2552,7 +2528,7 @@ static int em28xx_v4l2_init(struct em28xx *dev) | |||
| 2552 | v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock; | 2528 | v4l2->vbi_dev->queue->lock = &v4l2->vb_vbi_queue_lock; |
| 2553 | 2529 | ||
| 2554 | /* disable inapplicable ioctls */ | 2530 | /* disable inapplicable ioctls */ |
| 2555 | v4l2_disable_ioctl(v4l2->vdev, VIDIOC_S_PARM); | 2531 | v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_PARM); |
| 2556 | if (dev->tuner_type == TUNER_ABSENT) { | 2532 | if (dev->tuner_type == TUNER_ABSENT) { |
| 2557 | v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER); | 2533 | v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_G_TUNER); |
| 2558 | v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER); | 2534 | v4l2_disable_ioctl(v4l2->vbi_dev, VIDIOC_S_TUNER); |
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index b4c837d77e5d..84ef8efdb148 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h | |||
| @@ -524,7 +524,6 @@ struct em28xx_v4l2 { | |||
| 524 | int sensor_yres; | 524 | int sensor_yres; |
| 525 | int sensor_xtal; | 525 | int sensor_xtal; |
| 526 | 526 | ||
| 527 | int users; /* user count for exclusive use */ | ||
| 528 | int streaming_users; /* number of actively streaming users */ | 527 | int streaming_users; /* number of actively streaming users */ |
| 529 | 528 | ||
| 530 | u32 frequency; /* selected tuner frequency */ | 529 | u32 frequency; /* selected tuner frequency */ |
| @@ -576,13 +575,6 @@ struct em28xx_audio { | |||
| 576 | 575 | ||
| 577 | struct em28xx; | 576 | struct em28xx; |
| 578 | 577 | ||
| 579 | struct em28xx_fh { | ||
| 580 | struct v4l2_fh fh; | ||
| 581 | struct em28xx *dev; | ||
| 582 | |||
| 583 | enum v4l2_buf_type type; | ||
| 584 | }; | ||
| 585 | |||
| 586 | enum em28xx_i2c_algo_type { | 578 | enum em28xx_i2c_algo_type { |
| 587 | EM28XX_I2C_ALGO_EM28XX = 0, | 579 | EM28XX_I2C_ALGO_EM28XX = 0, |
| 588 | EM28XX_I2C_ALGO_EM2800, | 580 | EM28XX_I2C_ALGO_EM2800, |
diff --git a/drivers/media/usb/go7007/Kconfig b/drivers/media/usb/go7007/Kconfig new file mode 100644 index 000000000000..95a3af644a92 --- /dev/null +++ b/drivers/media/usb/go7007/Kconfig | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | config VIDEO_GO7007 | ||
| 2 | tristate "WIS GO7007 MPEG encoder support" | ||
| 3 | depends on VIDEO_DEV && I2C | ||
| 4 | depends on SND && USB | ||
| 5 | select VIDEOBUF2_VMALLOC | ||
| 6 | select VIDEO_TUNER | ||
| 7 | select CYPRESS_FIRMWARE | ||
| 8 | select SND_PCM | ||
| 9 | select VIDEO_SONY_BTF_MPX if MEDIA_SUBDRV_AUTOSELECT | ||
| 10 | select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT | ||
| 11 | select VIDEO_TW2804 if MEDIA_SUBDRV_AUTOSELECT | ||
| 12 | select VIDEO_TW9903 if MEDIA_SUBDRV_AUTOSELECT | ||
| 13 | select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT | ||
| 14 | select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT | ||
| 15 | select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT | ||
| 16 | ---help--- | ||
| 17 | This is a video4linux driver for the WIS GO7007 MPEG | ||
| 18 | encoder chip. | ||
| 19 | |||
| 20 | To compile this driver as a module, choose M here: the | ||
| 21 | module will be called go7007. | ||
| 22 | |||
| 23 | config VIDEO_GO7007_USB | ||
| 24 | tristate "WIS GO7007 USB support" | ||
| 25 | depends on VIDEO_GO7007 && USB | ||
| 26 | ---help--- | ||
| 27 | This is a video4linux driver for the WIS GO7007 MPEG | ||
| 28 | encoder chip over USB. | ||
| 29 | |||
| 30 | To compile this driver as a module, choose M here: the | ||
| 31 | module will be called go7007-usb. | ||
| 32 | |||
| 33 | config VIDEO_GO7007_LOADER | ||
| 34 | tristate "WIS GO7007 Loader support" | ||
| 35 | depends on VIDEO_GO7007 | ||
| 36 | default y | ||
| 37 | ---help--- | ||
| 38 | This is a go7007 firmware loader driver for the WIS GO7007 | ||
| 39 | MPEG encoder chip over USB. | ||
| 40 | |||
| 41 | To compile this driver as a module, choose M here: the | ||
| 42 | module will be called go7007-loader. | ||
| 43 | |||
| 44 | config VIDEO_GO7007_USB_S2250_BOARD | ||
| 45 | tristate "Sensoray 2250/2251 support" | ||
| 46 | depends on VIDEO_GO7007_USB && USB | ||
| 47 | ---help--- | ||
| 48 | This is a video4linux driver for the Sensoray 2250/2251 device. | ||
| 49 | |||
| 50 | To compile this driver as a module, choose M here: the | ||
| 51 | module will be called s2250. | ||
diff --git a/drivers/media/usb/go7007/Makefile b/drivers/media/usb/go7007/Makefile new file mode 100644 index 000000000000..e99287c3b828 --- /dev/null +++ b/drivers/media/usb/go7007/Makefile | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | obj-$(CONFIG_VIDEO_GO7007) += go7007.o | ||
| 2 | obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o | ||
| 3 | obj-$(CONFIG_VIDEO_GO7007_LOADER) += go7007-loader.o | ||
| 4 | obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o | ||
| 5 | |||
| 6 | go7007-y := go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \ | ||
| 7 | snd-go7007.o | ||
| 8 | |||
| 9 | s2250-y := s2250-board.o | ||
| 10 | |||
| 11 | ccflags-$(CONFIG_VIDEO_GO7007_LOADER:m=y) += -Idrivers/media/common | ||
diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c new file mode 100644 index 000000000000..95cffb771a62 --- /dev/null +++ b/drivers/media/usb/go7007/go7007-driver.c | |||
| @@ -0,0 +1,766 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/unistd.h> | ||
| 19 | #include <linux/time.h> | ||
| 20 | #include <linux/mm.h> | ||
| 21 | #include <linux/vmalloc.h> | ||
| 22 | #include <linux/device.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <linux/firmware.h> | ||
| 25 | #include <linux/mutex.h> | ||
| 26 | #include <linux/uaccess.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/videodev2.h> | ||
| 29 | #include <media/tuner.h> | ||
| 30 | #include <media/v4l2-common.h> | ||
| 31 | #include <media/v4l2-event.h> | ||
| 32 | |||
| 33 | #include "go7007-priv.h" | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Wait for an interrupt to be delivered from the GO7007SB and return | ||
| 37 | * the associated value and data. | ||
| 38 | * | ||
| 39 | * Must be called with the hw_lock held. | ||
| 40 | */ | ||
| 41 | int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) | ||
| 42 | { | ||
| 43 | go->interrupt_available = 0; | ||
| 44 | go->hpi_ops->read_interrupt(go); | ||
| 45 | if (wait_event_timeout(go->interrupt_waitq, | ||
| 46 | go->interrupt_available, 5*HZ) < 0) { | ||
| 47 | v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n"); | ||
| 48 | return -1; | ||
| 49 | } | ||
| 50 | if (!go->interrupt_available) | ||
| 51 | return -1; | ||
| 52 | go->interrupt_available = 0; | ||
| 53 | *value = go->interrupt_value & 0xfffe; | ||
| 54 | *data = go->interrupt_data; | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | EXPORT_SYMBOL(go7007_read_interrupt); | ||
| 58 | |||
| 59 | /* | ||
| 60 | * Read a register/address on the GO7007SB. | ||
| 61 | * | ||
| 62 | * Must be called with the hw_lock held. | ||
| 63 | */ | ||
| 64 | int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data) | ||
| 65 | { | ||
| 66 | int count = 100; | ||
| 67 | u16 value; | ||
| 68 | |||
| 69 | if (go7007_write_interrupt(go, 0x0010, addr) < 0) | ||
| 70 | return -EIO; | ||
| 71 | while (count-- > 0) { | ||
| 72 | if (go7007_read_interrupt(go, &value, data) == 0 && | ||
| 73 | value == 0xa000) | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | return -EIO; | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL(go7007_read_addr); | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Send the boot firmware to the encoder, which just wakes it up and lets | ||
| 82 | * us talk to the GPIO pins and on-board I2C adapter. | ||
| 83 | * | ||
| 84 | * Must be called with the hw_lock held. | ||
| 85 | */ | ||
| 86 | static int go7007_load_encoder(struct go7007 *go) | ||
| 87 | { | ||
| 88 | const struct firmware *fw_entry; | ||
| 89 | char fw_name[] = "go7007/go7007fw.bin"; | ||
| 90 | void *bounce; | ||
| 91 | int fw_len, rv = 0; | ||
| 92 | u16 intr_val, intr_data; | ||
| 93 | |||
| 94 | if (go->boot_fw == NULL) { | ||
| 95 | if (request_firmware(&fw_entry, fw_name, go->dev)) { | ||
| 96 | v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name); | ||
| 97 | return -1; | ||
| 98 | } | ||
| 99 | if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { | ||
| 100 | v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name); | ||
| 101 | release_firmware(fw_entry); | ||
| 102 | return -1; | ||
| 103 | } | ||
| 104 | fw_len = fw_entry->size - 16; | ||
| 105 | bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL); | ||
| 106 | if (bounce == NULL) { | ||
| 107 | v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len); | ||
| 108 | release_firmware(fw_entry); | ||
| 109 | return -1; | ||
| 110 | } | ||
| 111 | release_firmware(fw_entry); | ||
| 112 | go->boot_fw_len = fw_len; | ||
| 113 | go->boot_fw = bounce; | ||
| 114 | } | ||
| 115 | if (go7007_interface_reset(go) < 0 || | ||
| 116 | go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 || | ||
| 117 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || | ||
| 118 | (intr_val & ~0x1) != 0x5a5a) { | ||
| 119 | v4l2_err(go, "error transferring firmware\n"); | ||
| 120 | rv = -1; | ||
| 121 | } | ||
| 122 | return rv; | ||
| 123 | } | ||
| 124 | |||
| 125 | MODULE_FIRMWARE("go7007/go7007fw.bin"); | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Boot the encoder and register the I2C adapter if requested. Do the | ||
| 129 | * minimum initialization necessary, since the board-specific code may | ||
| 130 | * still need to probe the board ID. | ||
| 131 | * | ||
| 132 | * Must NOT be called with the hw_lock held. | ||
| 133 | */ | ||
| 134 | int go7007_boot_encoder(struct go7007 *go, int init_i2c) | ||
| 135 | { | ||
| 136 | int ret; | ||
| 137 | |||
| 138 | mutex_lock(&go->hw_lock); | ||
| 139 | ret = go7007_load_encoder(go); | ||
| 140 | mutex_unlock(&go->hw_lock); | ||
| 141 | if (ret < 0) | ||
| 142 | return -1; | ||
| 143 | if (!init_i2c) | ||
| 144 | return 0; | ||
| 145 | if (go7007_i2c_init(go) < 0) | ||
| 146 | return -1; | ||
| 147 | go->i2c_adapter_online = 1; | ||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | EXPORT_SYMBOL(go7007_boot_encoder); | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Configure any hardware-related registers in the GO7007, such as GPIO | ||
| 154 | * pins and bus parameters, which are board-specific. This assumes | ||
| 155 | * the boot firmware has already been downloaded. | ||
| 156 | * | ||
| 157 | * Must be called with the hw_lock held. | ||
| 158 | */ | ||
| 159 | static int go7007_init_encoder(struct go7007 *go) | ||
| 160 | { | ||
| 161 | if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) { | ||
| 162 | go7007_write_addr(go, 0x1000, 0x0811); | ||
| 163 | go7007_write_addr(go, 0x1000, 0x0c11); | ||
| 164 | } | ||
| 165 | switch (go->board_id) { | ||
| 166 | case GO7007_BOARDID_MATRIX_REV: | ||
| 167 | /* Set GPIO pin 0 to be an output (audio clock control) */ | ||
| 168 | go7007_write_addr(go, 0x3c82, 0x0001); | ||
| 169 | go7007_write_addr(go, 0x3c80, 0x00fe); | ||
| 170 | break; | ||
| 171 | case GO7007_BOARDID_ADLINK_MPG24: | ||
| 172 | /* set GPIO5 to be an output, currently low */ | ||
| 173 | go7007_write_addr(go, 0x3c82, 0x0000); | ||
| 174 | go7007_write_addr(go, 0x3c80, 0x00df); | ||
| 175 | break; | ||
| 176 | case GO7007_BOARDID_ADS_USBAV_709: | ||
| 177 | /* GPIO pin 0: audio clock control */ | ||
| 178 | /* pin 2: TW9906 reset */ | ||
| 179 | /* pin 3: capture LED */ | ||
| 180 | go7007_write_addr(go, 0x3c82, 0x000d); | ||
| 181 | go7007_write_addr(go, 0x3c80, 0x00f2); | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | ||
| 188 | * Send the boot firmware to the GO7007 and configure the registers. This | ||
| 189 | * is the only way to stop the encoder once it has started streaming video. | ||
| 190 | * | ||
| 191 | * Must be called with the hw_lock held. | ||
| 192 | */ | ||
| 193 | int go7007_reset_encoder(struct go7007 *go) | ||
| 194 | { | ||
| 195 | if (go7007_load_encoder(go) < 0) | ||
| 196 | return -1; | ||
| 197 | return go7007_init_encoder(go); | ||
| 198 | } | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Attempt to instantiate an I2C client by ID, probably loading a module. | ||
| 202 | */ | ||
| 203 | static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c) | ||
| 204 | { | ||
| 205 | struct go7007 *go = i2c_get_adapdata(adapter); | ||
| 206 | struct v4l2_device *v4l2_dev = &go->v4l2_dev; | ||
| 207 | struct v4l2_subdev *sd; | ||
| 208 | struct i2c_board_info info; | ||
| 209 | |||
| 210 | memset(&info, 0, sizeof(info)); | ||
| 211 | strlcpy(info.type, i2c->type, sizeof(info.type)); | ||
| 212 | info.addr = i2c->addr; | ||
| 213 | info.flags = i2c->flags; | ||
| 214 | |||
| 215 | sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL); | ||
| 216 | if (sd) { | ||
| 217 | if (i2c->is_video) | ||
| 218 | go->sd_video = sd; | ||
| 219 | if (i2c->is_audio) | ||
| 220 | go->sd_audio = sd; | ||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | pr_info("go7007: probing for module i2c:%s failed\n", i2c->type); | ||
| 225 | return -EINVAL; | ||
| 226 | } | ||
| 227 | |||
| 228 | /* | ||
| 229 | * Detach and unregister the encoder. The go7007 struct won't be freed | ||
| 230 | * until v4l2 finishes releasing its resources and all associated fds are | ||
| 231 | * closed by applications. | ||
| 232 | */ | ||
| 233 | static void go7007_remove(struct v4l2_device *v4l2_dev) | ||
| 234 | { | ||
| 235 | struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev); | ||
| 236 | |||
| 237 | v4l2_device_unregister(v4l2_dev); | ||
| 238 | if (go->hpi_ops->release) | ||
| 239 | go->hpi_ops->release(go); | ||
| 240 | if (go->i2c_adapter_online) { | ||
| 241 | i2c_del_adapter(&go->i2c_adapter); | ||
| 242 | go->i2c_adapter_online = 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | kfree(go->boot_fw); | ||
| 246 | go7007_v4l2_remove(go); | ||
| 247 | kfree(go); | ||
| 248 | } | ||
| 249 | |||
| 250 | /* | ||
| 251 | * Finalize the GO7007 hardware setup, register the on-board I2C adapter | ||
| 252 | * (if used on this board), load the I2C client driver for the sensor | ||
| 253 | * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2 | ||
| 254 | * interfaces. | ||
| 255 | * | ||
| 256 | * Must NOT be called with the hw_lock held. | ||
| 257 | */ | ||
| 258 | int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs) | ||
| 259 | { | ||
| 260 | int i, ret; | ||
| 261 | |||
| 262 | dev_info(go->dev, "go7007: registering new %s\n", go->name); | ||
| 263 | |||
| 264 | go->v4l2_dev.release = go7007_remove; | ||
| 265 | ret = v4l2_device_register(go->dev, &go->v4l2_dev); | ||
| 266 | if (ret < 0) | ||
| 267 | return ret; | ||
| 268 | |||
| 269 | mutex_lock(&go->hw_lock); | ||
| 270 | ret = go7007_init_encoder(go); | ||
| 271 | mutex_unlock(&go->hw_lock); | ||
| 272 | if (ret < 0) | ||
| 273 | return ret; | ||
| 274 | |||
| 275 | ret = go7007_v4l2_ctrl_init(go); | ||
| 276 | if (ret < 0) | ||
| 277 | return ret; | ||
| 278 | |||
| 279 | if (!go->i2c_adapter_online && | ||
| 280 | go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { | ||
| 281 | ret = go7007_i2c_init(go); | ||
| 282 | if (ret < 0) | ||
| 283 | return ret; | ||
| 284 | go->i2c_adapter_online = 1; | ||
| 285 | } | ||
| 286 | if (go->i2c_adapter_online) { | ||
| 287 | if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) { | ||
| 288 | /* Reset the TW9906 */ | ||
| 289 | go7007_write_addr(go, 0x3c82, 0x0009); | ||
| 290 | msleep(50); | ||
| 291 | go7007_write_addr(go, 0x3c82, 0x000d); | ||
| 292 | } | ||
| 293 | for (i = 0; i < num_i2c_devs; ++i) | ||
| 294 | init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]); | ||
| 295 | |||
| 296 | if (go->tuner_type >= 0) { | ||
| 297 | struct tuner_setup setup = { | ||
| 298 | .addr = ADDR_UNSET, | ||
| 299 | .type = go->tuner_type, | ||
| 300 | .mode_mask = T_ANALOG_TV, | ||
| 301 | }; | ||
| 302 | |||
| 303 | v4l2_device_call_all(&go->v4l2_dev, 0, tuner, | ||
| 304 | s_type_addr, &setup); | ||
| 305 | } | ||
| 306 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) | ||
| 307 | v4l2_subdev_call(go->sd_video, video, s_routing, | ||
| 308 | 0, 0, go->channel_number + 1); | ||
| 309 | } | ||
| 310 | |||
| 311 | ret = go7007_v4l2_init(go); | ||
| 312 | if (ret < 0) | ||
| 313 | return ret; | ||
| 314 | |||
| 315 | if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) { | ||
| 316 | go->audio_enabled = 1; | ||
| 317 | go7007_snd_init(go); | ||
| 318 | } | ||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | EXPORT_SYMBOL(go7007_register_encoder); | ||
| 322 | |||
| 323 | /* | ||
| 324 | * Send the encode firmware to the encoder, which will cause it | ||
| 325 | * to immediately start delivering the video and audio streams. | ||
| 326 | * | ||
| 327 | * Must be called with the hw_lock held. | ||
| 328 | */ | ||
| 329 | int go7007_start_encoder(struct go7007 *go) | ||
| 330 | { | ||
| 331 | u8 *fw; | ||
| 332 | int fw_len, rv = 0, i, x, y; | ||
| 333 | u16 intr_val, intr_data; | ||
| 334 | |||
| 335 | go->modet_enable = 0; | ||
| 336 | for (i = 0; i < 4; i++) | ||
| 337 | go->modet[i].enable = 0; | ||
| 338 | |||
| 339 | switch (v4l2_ctrl_g_ctrl(go->modet_mode)) { | ||
| 340 | case V4L2_DETECT_MD_MODE_GLOBAL: | ||
| 341 | memset(go->modet_map, 0, sizeof(go->modet_map)); | ||
| 342 | go->modet[0].enable = 1; | ||
| 343 | go->modet_enable = 1; | ||
| 344 | break; | ||
| 345 | case V4L2_DETECT_MD_MODE_REGION_GRID: | ||
| 346 | for (y = 0; y < go->height / 16; y++) { | ||
| 347 | for (x = 0; x < go->width / 16; x++) { | ||
| 348 | int idx = y * go->width / 16 + x; | ||
| 349 | |||
| 350 | go->modet[go->modet_map[idx]].enable = 1; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | go->modet_enable = 1; | ||
| 354 | break; | ||
| 355 | } | ||
| 356 | |||
| 357 | if (go->dvd_mode) | ||
| 358 | go->modet_enable = 0; | ||
| 359 | |||
| 360 | if (go7007_construct_fw_image(go, &fw, &fw_len) < 0) | ||
| 361 | return -1; | ||
| 362 | |||
| 363 | if (go7007_send_firmware(go, fw, fw_len) < 0 || | ||
| 364 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { | ||
| 365 | v4l2_err(&go->v4l2_dev, "error transferring firmware\n"); | ||
| 366 | rv = -1; | ||
| 367 | goto start_error; | ||
| 368 | } | ||
| 369 | |||
| 370 | go->state = STATE_DATA; | ||
| 371 | go->parse_length = 0; | ||
| 372 | go->seen_frame = 0; | ||
| 373 | if (go7007_stream_start(go) < 0) { | ||
| 374 | v4l2_err(&go->v4l2_dev, "error starting stream transfer\n"); | ||
| 375 | rv = -1; | ||
| 376 | goto start_error; | ||
| 377 | } | ||
| 378 | |||
| 379 | start_error: | ||
| 380 | kfree(fw); | ||
| 381 | return rv; | ||
| 382 | } | ||
| 383 | |||
| 384 | /* | ||
| 385 | * Store a byte in the current video buffer, if there is one. | ||
| 386 | */ | ||
| 387 | static inline void store_byte(struct go7007_buffer *vb, u8 byte) | ||
| 388 | { | ||
| 389 | if (vb && vb->vb.v4l2_planes[0].bytesused < GO7007_BUF_SIZE) { | ||
| 390 | u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); | ||
| 391 | |||
| 392 | ptr[vb->vb.v4l2_planes[0].bytesused++] = byte; | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb, | ||
| 397 | u32 motion_regions) | ||
| 398 | { | ||
| 399 | if (motion_regions != go->modet_event_status) { | ||
| 400 | struct v4l2_event ev = { | ||
| 401 | .type = V4L2_EVENT_MOTION_DET, | ||
| 402 | .u.motion_det = { | ||
| 403 | .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ, | ||
| 404 | .frame_sequence = vb->vb.v4l2_buf.sequence, | ||
| 405 | .region_mask = motion_regions, | ||
| 406 | }, | ||
| 407 | }; | ||
| 408 | |||
| 409 | v4l2_event_queue(&go->vdev, &ev); | ||
| 410 | go->modet_event_status = motion_regions; | ||
| 411 | } | ||
| 412 | } | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Determine regions with motion and send a motion detection event | ||
| 416 | * in case of changes. | ||
| 417 | */ | ||
| 418 | static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb) | ||
| 419 | { | ||
| 420 | u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused; | ||
| 421 | unsigned motion[4] = { 0, 0, 0, 0 }; | ||
| 422 | u32 motion_regions = 0; | ||
| 423 | unsigned stride = (go->width + 7) >> 3; | ||
| 424 | unsigned x, y; | ||
| 425 | int i; | ||
| 426 | |||
| 427 | for (i = 0; i < 216; ++i) | ||
| 428 | store_byte(vb, go->active_map[i]); | ||
| 429 | for (y = 0; y < go->height / 16; y++) { | ||
| 430 | for (x = 0; x < go->width / 16; x++) { | ||
| 431 | if (!(go->active_map[y * stride + (x >> 3)] & (1 << (x & 7)))) | ||
| 432 | continue; | ||
| 433 | motion[go->modet_map[y * (go->width / 16) + x]]++; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | motion_regions = ((motion[0] > 0) << 0) | | ||
| 437 | ((motion[1] > 0) << 1) | | ||
| 438 | ((motion[2] > 0) << 2) | | ||
| 439 | ((motion[3] > 0) << 3); | ||
| 440 | *bytesused -= 216; | ||
| 441 | go7007_set_motion_regions(go, vb, motion_regions); | ||
| 442 | } | ||
| 443 | |||
| 444 | /* | ||
| 445 | * Deliver the last video buffer and get a new one to start writing to. | ||
| 446 | */ | ||
| 447 | static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb) | ||
| 448 | { | ||
| 449 | u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused; | ||
| 450 | struct go7007_buffer *vb_tmp = NULL; | ||
| 451 | |||
| 452 | if (vb == NULL) { | ||
| 453 | spin_lock(&go->spinlock); | ||
| 454 | if (!list_empty(&go->vidq_active)) | ||
| 455 | vb = go->active_buf = | ||
| 456 | list_first_entry(&go->vidq_active, struct go7007_buffer, list); | ||
| 457 | spin_unlock(&go->spinlock); | ||
| 458 | go->next_seq++; | ||
| 459 | return vb; | ||
| 460 | } | ||
| 461 | |||
| 462 | vb->vb.v4l2_buf.sequence = go->next_seq++; | ||
| 463 | if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE) | ||
| 464 | go7007_motion_regions(go, vb); | ||
| 465 | else | ||
| 466 | go7007_set_motion_regions(go, vb, 0); | ||
| 467 | |||
| 468 | v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp); | ||
| 469 | vb_tmp = vb; | ||
| 470 | spin_lock(&go->spinlock); | ||
| 471 | list_del(&vb->list); | ||
| 472 | if (list_empty(&go->vidq_active)) | ||
| 473 | vb = NULL; | ||
| 474 | else | ||
| 475 | vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list); | ||
| 476 | go->active_buf = vb; | ||
| 477 | spin_unlock(&go->spinlock); | ||
| 478 | vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE); | ||
| 479 | return vb; | ||
| 480 | } | ||
| 481 | |||
| 482 | static void write_bitmap_word(struct go7007 *go) | ||
| 483 | { | ||
| 484 | int x, y, i, stride = ((go->width >> 4) + 7) >> 3; | ||
| 485 | |||
| 486 | for (i = 0; i < 16; ++i) { | ||
| 487 | y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4); | ||
| 488 | x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4); | ||
| 489 | if (stride * y + (x >> 3) < sizeof(go->active_map)) | ||
| 490 | go->active_map[stride * y + (x >> 3)] |= | ||
| 491 | (go->modet_word & 1) << (x & 0x7); | ||
| 492 | go->modet_word >>= 1; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | /* | ||
| 497 | * Parse a chunk of the video stream into frames. The frames are not | ||
| 498 | * delimited by the hardware, so we have to parse the frame boundaries | ||
| 499 | * based on the type of video stream we're receiving. | ||
| 500 | */ | ||
| 501 | void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) | ||
| 502 | { | ||
| 503 | struct go7007_buffer *vb = go->active_buf; | ||
| 504 | int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1; | ||
| 505 | |||
| 506 | switch (go->format) { | ||
| 507 | case V4L2_PIX_FMT_MPEG4: | ||
| 508 | seq_start_code = 0xB0; | ||
| 509 | gop_start_code = 0xB3; | ||
| 510 | frame_start_code = 0xB6; | ||
| 511 | break; | ||
| 512 | case V4L2_PIX_FMT_MPEG1: | ||
| 513 | case V4L2_PIX_FMT_MPEG2: | ||
| 514 | seq_start_code = 0xB3; | ||
| 515 | gop_start_code = 0xB8; | ||
| 516 | frame_start_code = 0x00; | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | |||
| 520 | for (i = 0; i < length; ++i) { | ||
| 521 | if (vb && vb->vb.v4l2_planes[0].bytesused >= GO7007_BUF_SIZE - 3) { | ||
| 522 | v4l2_info(&go->v4l2_dev, "dropping oversized frame\n"); | ||
| 523 | vb->vb.v4l2_planes[0].bytesused = 0; | ||
| 524 | vb->frame_offset = 0; | ||
| 525 | vb->modet_active = 0; | ||
| 526 | vb = go->active_buf = NULL; | ||
| 527 | } | ||
| 528 | |||
| 529 | switch (go->state) { | ||
| 530 | case STATE_DATA: | ||
| 531 | switch (buf[i]) { | ||
| 532 | case 0x00: | ||
| 533 | go->state = STATE_00; | ||
| 534 | break; | ||
| 535 | case 0xFF: | ||
| 536 | go->state = STATE_FF; | ||
| 537 | break; | ||
| 538 | default: | ||
| 539 | store_byte(vb, buf[i]); | ||
| 540 | break; | ||
| 541 | } | ||
| 542 | break; | ||
| 543 | case STATE_00: | ||
| 544 | switch (buf[i]) { | ||
| 545 | case 0x00: | ||
| 546 | go->state = STATE_00_00; | ||
| 547 | break; | ||
| 548 | case 0xFF: | ||
| 549 | store_byte(vb, 0x00); | ||
| 550 | go->state = STATE_FF; | ||
| 551 | break; | ||
| 552 | default: | ||
| 553 | store_byte(vb, 0x00); | ||
| 554 | store_byte(vb, buf[i]); | ||
| 555 | go->state = STATE_DATA; | ||
| 556 | break; | ||
| 557 | } | ||
| 558 | break; | ||
| 559 | case STATE_00_00: | ||
| 560 | switch (buf[i]) { | ||
| 561 | case 0x00: | ||
| 562 | store_byte(vb, 0x00); | ||
| 563 | /* go->state remains STATE_00_00 */ | ||
| 564 | break; | ||
| 565 | case 0x01: | ||
| 566 | go->state = STATE_00_00_01; | ||
| 567 | break; | ||
| 568 | case 0xFF: | ||
| 569 | store_byte(vb, 0x00); | ||
| 570 | store_byte(vb, 0x00); | ||
| 571 | go->state = STATE_FF; | ||
| 572 | break; | ||
| 573 | default: | ||
| 574 | store_byte(vb, 0x00); | ||
| 575 | store_byte(vb, 0x00); | ||
| 576 | store_byte(vb, buf[i]); | ||
| 577 | go->state = STATE_DATA; | ||
| 578 | break; | ||
| 579 | } | ||
| 580 | break; | ||
| 581 | case STATE_00_00_01: | ||
| 582 | if (buf[i] == 0xF8 && go->modet_enable == 0) { | ||
| 583 | /* MODET start code, but MODET not enabled */ | ||
| 584 | store_byte(vb, 0x00); | ||
| 585 | store_byte(vb, 0x00); | ||
| 586 | store_byte(vb, 0x01); | ||
| 587 | store_byte(vb, 0xF8); | ||
| 588 | go->state = STATE_DATA; | ||
| 589 | break; | ||
| 590 | } | ||
| 591 | /* If this is the start of a new MPEG frame, | ||
| 592 | * get a new buffer */ | ||
| 593 | if ((go->format == V4L2_PIX_FMT_MPEG1 || | ||
| 594 | go->format == V4L2_PIX_FMT_MPEG2 || | ||
| 595 | go->format == V4L2_PIX_FMT_MPEG4) && | ||
| 596 | (buf[i] == seq_start_code || | ||
| 597 | buf[i] == gop_start_code || | ||
| 598 | buf[i] == frame_start_code)) { | ||
| 599 | if (vb == NULL || go->seen_frame) | ||
| 600 | vb = frame_boundary(go, vb); | ||
| 601 | go->seen_frame = buf[i] == frame_start_code; | ||
| 602 | if (vb && go->seen_frame) | ||
| 603 | vb->frame_offset = vb->vb.v4l2_planes[0].bytesused; | ||
| 604 | } | ||
| 605 | /* Handle any special chunk types, or just write the | ||
| 606 | * start code to the (potentially new) buffer */ | ||
| 607 | switch (buf[i]) { | ||
| 608 | case 0xF5: /* timestamp */ | ||
| 609 | go->parse_length = 12; | ||
| 610 | go->state = STATE_UNPARSED; | ||
| 611 | break; | ||
| 612 | case 0xF6: /* vbi */ | ||
| 613 | go->state = STATE_VBI_LEN_A; | ||
| 614 | break; | ||
| 615 | case 0xF8: /* MD map */ | ||
| 616 | go->parse_length = 0; | ||
| 617 | memset(go->active_map, 0, | ||
| 618 | sizeof(go->active_map)); | ||
| 619 | go->state = STATE_MODET_MAP; | ||
| 620 | break; | ||
| 621 | case 0xFF: /* Potential JPEG start code */ | ||
| 622 | store_byte(vb, 0x00); | ||
| 623 | store_byte(vb, 0x00); | ||
| 624 | store_byte(vb, 0x01); | ||
| 625 | go->state = STATE_FF; | ||
| 626 | break; | ||
| 627 | default: | ||
| 628 | store_byte(vb, 0x00); | ||
| 629 | store_byte(vb, 0x00); | ||
| 630 | store_byte(vb, 0x01); | ||
| 631 | store_byte(vb, buf[i]); | ||
| 632 | go->state = STATE_DATA; | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | break; | ||
| 636 | case STATE_FF: | ||
| 637 | switch (buf[i]) { | ||
| 638 | case 0x00: | ||
| 639 | store_byte(vb, 0xFF); | ||
| 640 | go->state = STATE_00; | ||
| 641 | break; | ||
| 642 | case 0xFF: | ||
| 643 | store_byte(vb, 0xFF); | ||
| 644 | /* go->state remains STATE_FF */ | ||
| 645 | break; | ||
| 646 | case 0xD8: | ||
| 647 | if (go->format == V4L2_PIX_FMT_MJPEG) | ||
| 648 | vb = frame_boundary(go, vb); | ||
| 649 | /* fall through */ | ||
| 650 | default: | ||
| 651 | store_byte(vb, 0xFF); | ||
| 652 | store_byte(vb, buf[i]); | ||
| 653 | go->state = STATE_DATA; | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | break; | ||
| 657 | case STATE_VBI_LEN_A: | ||
| 658 | go->parse_length = buf[i] << 8; | ||
| 659 | go->state = STATE_VBI_LEN_B; | ||
| 660 | break; | ||
| 661 | case STATE_VBI_LEN_B: | ||
| 662 | go->parse_length |= buf[i]; | ||
| 663 | if (go->parse_length > 0) | ||
| 664 | go->state = STATE_UNPARSED; | ||
| 665 | else | ||
| 666 | go->state = STATE_DATA; | ||
| 667 | break; | ||
| 668 | case STATE_MODET_MAP: | ||
| 669 | if (go->parse_length < 204) { | ||
| 670 | if (go->parse_length & 1) { | ||
| 671 | go->modet_word |= buf[i]; | ||
| 672 | write_bitmap_word(go); | ||
| 673 | } else | ||
| 674 | go->modet_word = buf[i] << 8; | ||
| 675 | } else if (go->parse_length == 207 && vb) { | ||
| 676 | vb->modet_active = buf[i]; | ||
| 677 | } | ||
| 678 | if (++go->parse_length == 208) | ||
| 679 | go->state = STATE_DATA; | ||
| 680 | break; | ||
| 681 | case STATE_UNPARSED: | ||
| 682 | if (--go->parse_length == 0) | ||
| 683 | go->state = STATE_DATA; | ||
| 684 | break; | ||
| 685 | } | ||
| 686 | } | ||
| 687 | } | ||
| 688 | EXPORT_SYMBOL(go7007_parse_video_stream); | ||
| 689 | |||
| 690 | /* | ||
| 691 | * Allocate a new go7007 struct. Used by the hardware-specific probe. | ||
| 692 | */ | ||
| 693 | struct go7007 *go7007_alloc(const struct go7007_board_info *board, | ||
| 694 | struct device *dev) | ||
| 695 | { | ||
| 696 | struct go7007 *go; | ||
| 697 | int i; | ||
| 698 | |||
| 699 | go = kzalloc(sizeof(struct go7007), GFP_KERNEL); | ||
| 700 | if (go == NULL) | ||
| 701 | return NULL; | ||
| 702 | go->dev = dev; | ||
| 703 | go->board_info = board; | ||
| 704 | go->board_id = 0; | ||
| 705 | go->tuner_type = -1; | ||
| 706 | go->channel_number = 0; | ||
| 707 | go->name[0] = 0; | ||
| 708 | mutex_init(&go->hw_lock); | ||
| 709 | init_waitqueue_head(&go->frame_waitq); | ||
| 710 | spin_lock_init(&go->spinlock); | ||
| 711 | go->status = STATUS_INIT; | ||
| 712 | memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter)); | ||
| 713 | go->i2c_adapter_online = 0; | ||
| 714 | go->interrupt_available = 0; | ||
| 715 | init_waitqueue_head(&go->interrupt_waitq); | ||
| 716 | go->input = 0; | ||
| 717 | go7007_update_board(go); | ||
| 718 | go->encoder_h_halve = 0; | ||
| 719 | go->encoder_v_halve = 0; | ||
| 720 | go->encoder_subsample = 0; | ||
| 721 | go->format = V4L2_PIX_FMT_MJPEG; | ||
| 722 | go->bitrate = 1500000; | ||
| 723 | go->fps_scale = 1; | ||
| 724 | go->pali = 0; | ||
| 725 | go->aspect_ratio = GO7007_RATIO_1_1; | ||
| 726 | go->gop_size = 0; | ||
| 727 | go->ipb = 0; | ||
| 728 | go->closed_gop = 0; | ||
| 729 | go->repeat_seqhead = 0; | ||
| 730 | go->seq_header_enable = 0; | ||
| 731 | go->gop_header_enable = 0; | ||
| 732 | go->dvd_mode = 0; | ||
| 733 | go->interlace_coding = 0; | ||
| 734 | for (i = 0; i < 4; ++i) | ||
| 735 | go->modet[i].enable = 0; | ||
| 736 | for (i = 0; i < 1624; ++i) | ||
| 737 | go->modet_map[i] = 0; | ||
| 738 | go->audio_deliver = NULL; | ||
| 739 | go->audio_enabled = 0; | ||
| 740 | |||
| 741 | return go; | ||
| 742 | } | ||
| 743 | EXPORT_SYMBOL(go7007_alloc); | ||
| 744 | |||
| 745 | void go7007_update_board(struct go7007 *go) | ||
| 746 | { | ||
| 747 | const struct go7007_board_info *board = go->board_info; | ||
| 748 | |||
| 749 | if (board->sensor_flags & GO7007_SENSOR_TV) { | ||
| 750 | go->standard = GO7007_STD_NTSC; | ||
| 751 | go->std = V4L2_STD_NTSC_M; | ||
| 752 | go->width = 720; | ||
| 753 | go->height = 480; | ||
| 754 | go->sensor_framerate = 30000; | ||
| 755 | } else { | ||
| 756 | go->standard = GO7007_STD_OTHER; | ||
| 757 | go->width = board->sensor_width; | ||
| 758 | go->height = board->sensor_height; | ||
| 759 | go->sensor_framerate = board->sensor_framerate; | ||
| 760 | } | ||
| 761 | go->encoder_v_offset = board->sensor_v_offset; | ||
| 762 | go->encoder_h_offset = board->sensor_h_offset; | ||
| 763 | } | ||
| 764 | EXPORT_SYMBOL(go7007_update_board); | ||
| 765 | |||
| 766 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c new file mode 100644 index 000000000000..5f4c9b9e899a --- /dev/null +++ b/drivers/media/usb/go7007/go7007-fw.c | |||
| @@ -0,0 +1,1628 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * This file contains code to generate a firmware image for the GO7007SB | ||
| 16 | * encoder. Much of the firmware is read verbatim from a file, but some of | ||
| 17 | * it concerning bitrate control and other things that can be configured at | ||
| 18 | * run-time are generated dynamically. Note that the format headers | ||
| 19 | * generated here do not affect the functioning of the encoder; they are | ||
| 20 | * merely parroted back to the host at the start of each frame. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/time.h> | ||
| 25 | #include <linux/mm.h> | ||
| 26 | #include <linux/device.h> | ||
| 27 | #include <linux/i2c.h> | ||
| 28 | #include <linux/firmware.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <asm/byteorder.h> | ||
| 31 | |||
| 32 | #include "go7007-priv.h" | ||
| 33 | |||
| 34 | #define GO7007_FW_NAME "go7007/go7007tv.bin" | ||
| 35 | |||
| 36 | /* Constants used in the source firmware image to describe code segments */ | ||
| 37 | |||
| 38 | #define FLAG_MODE_MJPEG (1) | ||
| 39 | #define FLAG_MODE_MPEG1 (1<<1) | ||
| 40 | #define FLAG_MODE_MPEG2 (1<<2) | ||
| 41 | #define FLAG_MODE_MPEG4 (1<<3) | ||
| 42 | #define FLAG_MODE_H263 (1<<4) | ||
| 43 | #define FLAG_MODE_ALL (FLAG_MODE_MJPEG | FLAG_MODE_MPEG1 | \ | ||
| 44 | FLAG_MODE_MPEG2 | FLAG_MODE_MPEG4 | \ | ||
| 45 | FLAG_MODE_H263) | ||
| 46 | #define FLAG_SPECIAL (1<<8) | ||
| 47 | |||
| 48 | #define SPECIAL_FRM_HEAD 0 | ||
| 49 | #define SPECIAL_BRC_CTRL 1 | ||
| 50 | #define SPECIAL_CONFIG 2 | ||
| 51 | #define SPECIAL_SEQHEAD 3 | ||
| 52 | #define SPECIAL_AV_SYNC 4 | ||
| 53 | #define SPECIAL_FINAL 5 | ||
| 54 | #define SPECIAL_AUDIO 6 | ||
| 55 | #define SPECIAL_MODET 7 | ||
| 56 | |||
| 57 | /* Little data class for creating MPEG headers bit-by-bit */ | ||
| 58 | |||
| 59 | struct code_gen { | ||
| 60 | unsigned char *p; /* destination */ | ||
| 61 | u32 a; /* collects bits at the top of the variable */ | ||
| 62 | int b; /* bit position of most recently-written bit */ | ||
| 63 | int len; /* written out so far */ | ||
| 64 | }; | ||
| 65 | |||
| 66 | #define CODE_GEN(name, dest) struct code_gen name = { dest, 0, 32, 0 } | ||
| 67 | |||
| 68 | #define CODE_ADD(name, val, length) do { \ | ||
| 69 | name.b -= (length); \ | ||
| 70 | name.a |= (val) << name.b; \ | ||
| 71 | while (name.b <= 24) { \ | ||
| 72 | *name.p = name.a >> 24; \ | ||
| 73 | ++name.p; \ | ||
| 74 | name.a <<= 8; \ | ||
| 75 | name.b += 8; \ | ||
| 76 | name.len += 8; \ | ||
| 77 | } \ | ||
| 78 | } while (0) | ||
| 79 | |||
| 80 | #define CODE_LENGTH(name) (name.len + (32 - name.b)) | ||
| 81 | |||
| 82 | /* Tables for creating the bitrate control data */ | ||
| 83 | |||
| 84 | static const s16 converge_speed_ip[101] = { | ||
| 85 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | ||
| 86 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | ||
| 87 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | ||
| 88 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, | ||
| 89 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, | ||
| 90 | 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, | ||
| 91 | 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, | ||
| 92 | 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, | ||
| 93 | 19, 20, 22, 23, 25, 27, 30, 32, 35, 38, | ||
| 94 | 41, 45, 49, 53, 58, 63, 69, 76, 83, 91, | ||
| 95 | 100 | ||
| 96 | }; | ||
| 97 | |||
| 98 | static const s16 converge_speed_ipb[101] = { | ||
| 99 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | ||
| 100 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | ||
| 101 | 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, | ||
| 102 | 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, | ||
| 103 | 6, 6, 6, 7, 7, 7, 7, 8, 8, 9, | ||
| 104 | 9, 9, 10, 10, 11, 12, 12, 13, 14, 14, | ||
| 105 | 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, | ||
| 106 | 28, 30, 32, 34, 37, 40, 42, 46, 49, 53, | ||
| 107 | 57, 61, 66, 71, 77, 83, 90, 97, 106, 115, | ||
| 108 | 125, 135, 147, 161, 175, 191, 209, 228, 249, 273, | ||
| 109 | 300 | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const s16 LAMBDA_table[4][101] = { | ||
| 113 | { 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, | ||
| 114 | 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, | ||
| 115 | 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, | ||
| 116 | 27, 27, 28, 28, 29, 29, 30, 31, 31, 32, | ||
| 117 | 32, 33, 33, 34, 35, 35, 36, 37, 37, 38, | ||
| 118 | 39, 39, 40, 41, 42, 42, 43, 44, 45, 46, | ||
| 119 | 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 120 | 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, | ||
| 121 | 67, 68, 69, 70, 72, 73, 74, 76, 77, 78, | ||
| 122 | 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, | ||
| 123 | 96 | ||
| 124 | }, | ||
| 125 | { | ||
| 126 | 20, 20, 20, 21, 21, 21, 22, 22, 23, 23, | ||
| 127 | 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, | ||
| 128 | 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, | ||
| 129 | 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, | ||
| 130 | 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, | ||
| 131 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, | ||
| 132 | 58, 59, 60, 61, 62, 64, 65, 66, 67, 68, | ||
| 133 | 70, 71, 72, 73, 75, 76, 78, 79, 80, 82, | ||
| 134 | 83, 85, 86, 88, 90, 91, 93, 95, 96, 98, | ||
| 135 | 100, 102, 103, 105, 107, 109, 111, 113, 115, 117, | ||
| 136 | 120 | ||
| 137 | }, | ||
| 138 | { | ||
| 139 | 24, 24, 24, 25, 25, 26, 26, 27, 27, 28, | ||
| 140 | 28, 29, 29, 30, 30, 31, 31, 32, 33, 33, | ||
| 141 | 34, 34, 35, 36, 36, 37, 38, 38, 39, 40, | ||
| 142 | 41, 41, 42, 43, 44, 44, 45, 46, 47, 48, | ||
| 143 | 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, | ||
| 144 | 58, 59, 60, 62, 63, 64, 65, 66, 67, 69, | ||
| 145 | 70, 71, 72, 74, 75, 76, 78, 79, 81, 82, | ||
| 146 | 84, 85, 87, 88, 90, 92, 93, 95, 97, 98, | ||
| 147 | 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, | ||
| 148 | 120, 122, 124, 127, 129, 131, 134, 136, 138, 141, | ||
| 149 | 144 | ||
| 150 | }, | ||
| 151 | { | ||
| 152 | 32, 32, 33, 33, 34, 34, 35, 36, 36, 37, | ||
| 153 | 38, 38, 39, 40, 41, 41, 42, 43, 44, 44, | ||
| 154 | 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, | ||
| 155 | 54, 55, 56, 57, 58, 59, 60, 62, 63, 64, | ||
| 156 | 65, 66, 67, 69, 70, 71, 72, 74, 75, 76, | ||
| 157 | 78, 79, 81, 82, 84, 85, 87, 88, 90, 92, | ||
| 158 | 93, 95, 97, 98, 100, 102, 104, 106, 108, 110, | ||
| 159 | 112, 114, 116, 118, 120, 122, 124, 127, 129, 131, | ||
| 160 | 134, 136, 139, 141, 144, 146, 149, 152, 154, 157, | ||
| 161 | 160, 163, 166, 169, 172, 175, 178, 181, 185, 188, | ||
| 162 | 192 | ||
| 163 | } | ||
| 164 | }; | ||
| 165 | |||
| 166 | /* MPEG blank frame generation tables */ | ||
| 167 | |||
| 168 | enum mpeg_frame_type { | ||
| 169 | PFRAME, | ||
| 170 | BFRAME_PRE, | ||
| 171 | BFRAME_POST, | ||
| 172 | BFRAME_BIDIR, | ||
| 173 | BFRAME_EMPTY | ||
| 174 | }; | ||
| 175 | |||
| 176 | static const u32 addrinctab[33][2] = { | ||
| 177 | { 0x01, 1 }, { 0x03, 3 }, { 0x02, 3 }, { 0x03, 4 }, | ||
| 178 | { 0x02, 4 }, { 0x03, 5 }, { 0x02, 5 }, { 0x07, 7 }, | ||
| 179 | { 0x06, 7 }, { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 }, | ||
| 180 | { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, { 0x17, 10 }, | ||
| 181 | { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 }, | ||
| 182 | { 0x12, 10 }, { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 }, | ||
| 183 | { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 }, | ||
| 184 | { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 }, | ||
| 185 | { 0x18, 11 } | ||
| 186 | }; | ||
| 187 | |||
| 188 | /* Standard JPEG tables */ | ||
| 189 | |||
| 190 | static const u8 default_intra_quant_table[] = { | ||
| 191 | 8, 16, 19, 22, 26, 27, 29, 34, | ||
| 192 | 16, 16, 22, 24, 27, 29, 34, 37, | ||
| 193 | 19, 22, 26, 27, 29, 34, 34, 38, | ||
| 194 | 22, 22, 26, 27, 29, 34, 37, 40, | ||
| 195 | 22, 26, 27, 29, 32, 35, 40, 48, | ||
| 196 | 26, 27, 29, 32, 35, 40, 48, 58, | ||
| 197 | 26, 27, 29, 34, 38, 46, 56, 69, | ||
| 198 | 27, 29, 35, 38, 46, 56, 69, 83 | ||
| 199 | }; | ||
| 200 | |||
| 201 | static const u8 bits_dc_luminance[] = { | ||
| 202 | 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 | ||
| 203 | }; | ||
| 204 | |||
| 205 | static const u8 val_dc_luminance[] = { | ||
| 206 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 | ||
| 207 | }; | ||
| 208 | |||
| 209 | static const u8 bits_dc_chrominance[] = { | ||
| 210 | 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 | ||
| 211 | }; | ||
| 212 | |||
| 213 | static const u8 val_dc_chrominance[] = { | ||
| 214 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 | ||
| 215 | }; | ||
| 216 | |||
| 217 | static const u8 bits_ac_luminance[] = { | ||
| 218 | 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d | ||
| 219 | }; | ||
| 220 | |||
| 221 | static const u8 val_ac_luminance[] = { | ||
| 222 | 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, | ||
| 223 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, | ||
| 224 | 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, | ||
| 225 | 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, | ||
| 226 | 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, | ||
| 227 | 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, | ||
| 228 | 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, | ||
| 229 | 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, | ||
| 230 | 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, | ||
| 231 | 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | ||
| 232 | 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, | ||
| 233 | 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, | ||
| 234 | 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, | ||
| 235 | 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, | ||
| 236 | 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||
| 237 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, | ||
| 238 | 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, | ||
| 239 | 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, | ||
| 240 | 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, | ||
| 241 | 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||
| 242 | 0xf9, 0xfa | ||
| 243 | }; | ||
| 244 | |||
| 245 | static const u8 bits_ac_chrominance[] = { | ||
| 246 | 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 | ||
| 247 | }; | ||
| 248 | |||
| 249 | static const u8 val_ac_chrominance[] = { | ||
| 250 | 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, | ||
| 251 | 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, | ||
| 252 | 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, | ||
| 253 | 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, | ||
| 254 | 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, | ||
| 255 | 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, | ||
| 256 | 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, | ||
| 257 | 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, | ||
| 258 | 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | ||
| 259 | 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | ||
| 260 | 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | ||
| 261 | 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | ||
| 262 | 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, | ||
| 263 | 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | ||
| 264 | 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, | ||
| 265 | 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, | ||
| 266 | 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, | ||
| 267 | 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, | ||
| 268 | 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | ||
| 269 | 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||
| 270 | 0xf9, 0xfa | ||
| 271 | }; | ||
| 272 | |||
| 273 | /* Zig-zag mapping for quant table | ||
| 274 | * | ||
| 275 | * OK, let's do this mapping on the actual table above so it doesn't have | ||
| 276 | * to be done on the fly. | ||
| 277 | */ | ||
| 278 | static const int zz[64] = { | ||
| 279 | 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, | ||
| 280 | 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, | ||
| 281 | 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, | ||
| 282 | 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 | ||
| 283 | }; | ||
| 284 | |||
| 285 | static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space) | ||
| 286 | { | ||
| 287 | int i, cnt = pkg_cnt * 32; | ||
| 288 | |||
| 289 | if (space < cnt) | ||
| 290 | return -1; | ||
| 291 | |||
| 292 | for (i = 0; i < cnt; ++i) | ||
| 293 | dest[i] = cpu_to_le16p(src + i); | ||
| 294 | |||
| 295 | return cnt; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q) | ||
| 299 | { | ||
| 300 | int i, p = 0; | ||
| 301 | |||
| 302 | buf[p++] = 0xff; | ||
| 303 | buf[p++] = 0xd8; | ||
| 304 | buf[p++] = 0xff; | ||
| 305 | buf[p++] = 0xdb; | ||
| 306 | buf[p++] = 0; | ||
| 307 | buf[p++] = 2 + 65; | ||
| 308 | buf[p++] = 0; | ||
| 309 | buf[p++] = default_intra_quant_table[0]; | ||
| 310 | for (i = 1; i < 64; ++i) | ||
| 311 | /* buf[p++] = (default_intra_quant_table[i] * q) >> 3; */ | ||
| 312 | buf[p++] = (default_intra_quant_table[zz[i]] * q) >> 3; | ||
| 313 | buf[p++] = 0xff; | ||
| 314 | buf[p++] = 0xc0; | ||
| 315 | buf[p++] = 0; | ||
| 316 | buf[p++] = 17; | ||
| 317 | buf[p++] = 8; | ||
| 318 | buf[p++] = go->height >> 8; | ||
| 319 | buf[p++] = go->height & 0xff; | ||
| 320 | buf[p++] = go->width >> 8; | ||
| 321 | buf[p++] = go->width & 0xff; | ||
| 322 | buf[p++] = 3; | ||
| 323 | buf[p++] = 1; | ||
| 324 | buf[p++] = 0x22; | ||
| 325 | buf[p++] = 0; | ||
| 326 | buf[p++] = 2; | ||
| 327 | buf[p++] = 0x11; | ||
| 328 | buf[p++] = 0; | ||
| 329 | buf[p++] = 3; | ||
| 330 | buf[p++] = 0x11; | ||
| 331 | buf[p++] = 0; | ||
| 332 | buf[p++] = 0xff; | ||
| 333 | buf[p++] = 0xc4; | ||
| 334 | buf[p++] = 418 >> 8; | ||
| 335 | buf[p++] = 418 & 0xff; | ||
| 336 | buf[p++] = 0x00; | ||
| 337 | memcpy(buf + p, bits_dc_luminance + 1, 16); | ||
| 338 | p += 16; | ||
| 339 | memcpy(buf + p, val_dc_luminance, sizeof(val_dc_luminance)); | ||
| 340 | p += sizeof(val_dc_luminance); | ||
| 341 | buf[p++] = 0x01; | ||
| 342 | memcpy(buf + p, bits_dc_chrominance + 1, 16); | ||
| 343 | p += 16; | ||
| 344 | memcpy(buf + p, val_dc_chrominance, sizeof(val_dc_chrominance)); | ||
| 345 | p += sizeof(val_dc_chrominance); | ||
| 346 | buf[p++] = 0x10; | ||
| 347 | memcpy(buf + p, bits_ac_luminance + 1, 16); | ||
| 348 | p += 16; | ||
| 349 | memcpy(buf + p, val_ac_luminance, sizeof(val_ac_luminance)); | ||
| 350 | p += sizeof(val_ac_luminance); | ||
| 351 | buf[p++] = 0x11; | ||
| 352 | memcpy(buf + p, bits_ac_chrominance + 1, 16); | ||
| 353 | p += 16; | ||
| 354 | memcpy(buf + p, val_ac_chrominance, sizeof(val_ac_chrominance)); | ||
| 355 | p += sizeof(val_ac_chrominance); | ||
| 356 | buf[p++] = 0xff; | ||
| 357 | buf[p++] = 0xda; | ||
| 358 | buf[p++] = 0; | ||
| 359 | buf[p++] = 12; | ||
| 360 | buf[p++] = 3; | ||
| 361 | buf[p++] = 1; | ||
| 362 | buf[p++] = 0x00; | ||
| 363 | buf[p++] = 2; | ||
| 364 | buf[p++] = 0x11; | ||
| 365 | buf[p++] = 3; | ||
| 366 | buf[p++] = 0x11; | ||
| 367 | buf[p++] = 0; | ||
| 368 | buf[p++] = 63; | ||
| 369 | buf[p++] = 0; | ||
| 370 | return p; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space) | ||
| 374 | { | ||
| 375 | u8 *buf; | ||
| 376 | u16 mem = 0x3e00; | ||
| 377 | unsigned int addr = 0x19; | ||
| 378 | int size = 0, i, off = 0, chunk; | ||
| 379 | |||
| 380 | buf = kzalloc(4096, GFP_KERNEL); | ||
| 381 | if (buf == NULL) | ||
| 382 | return -1; | ||
| 383 | |||
| 384 | for (i = 1; i < 32; ++i) { | ||
| 385 | mjpeg_frame_header(go, buf + size, i); | ||
| 386 | size += 80; | ||
| 387 | } | ||
| 388 | chunk = mjpeg_frame_header(go, buf + size, 1); | ||
| 389 | memmove(buf + size, buf + size + 80, chunk - 80); | ||
| 390 | size += chunk - 80; | ||
| 391 | |||
| 392 | for (i = 0; i < size; i += chunk * 2) { | ||
| 393 | if (space - off < 32) { | ||
| 394 | off = -1; | ||
| 395 | goto done; | ||
| 396 | } | ||
| 397 | |||
| 398 | code[off + 1] = __cpu_to_le16(0x8000 | mem); | ||
| 399 | |||
| 400 | chunk = 28; | ||
| 401 | if (mem + chunk > 0x4000) | ||
| 402 | chunk = 0x4000 - mem; | ||
| 403 | if (i + 2 * chunk > size) | ||
| 404 | chunk = (size - i) / 2; | ||
| 405 | |||
| 406 | if (chunk < 28) { | ||
| 407 | code[off] = __cpu_to_le16(0x4000 | chunk); | ||
| 408 | code[off + 31] = __cpu_to_le16(addr++); | ||
| 409 | mem = 0x3e00; | ||
| 410 | } else { | ||
| 411 | code[off] = __cpu_to_le16(0x1000 | 28); | ||
| 412 | code[off + 31] = 0; | ||
| 413 | mem += 28; | ||
| 414 | } | ||
| 415 | |||
| 416 | memcpy(&code[off + 2], buf + i, chunk * 2); | ||
| 417 | off += 32; | ||
| 418 | } | ||
| 419 | done: | ||
| 420 | kfree(buf); | ||
| 421 | return off; | ||
| 422 | } | ||
| 423 | |||
| 424 | static int mpeg1_frame_header(struct go7007 *go, unsigned char *buf, | ||
| 425 | int modulo, int pict_struct, enum mpeg_frame_type frame) | ||
| 426 | { | ||
| 427 | int i, j, mb_code, mb_len; | ||
| 428 | int rows = go->interlace_coding ? go->height / 32 : go->height / 16; | ||
| 429 | CODE_GEN(c, buf + 6); | ||
| 430 | |||
| 431 | switch (frame) { | ||
| 432 | case PFRAME: | ||
| 433 | mb_code = 0x1; | ||
| 434 | mb_len = 3; | ||
| 435 | break; | ||
| 436 | case BFRAME_PRE: | ||
| 437 | mb_code = 0x2; | ||
| 438 | mb_len = 4; | ||
| 439 | break; | ||
| 440 | case BFRAME_POST: | ||
| 441 | mb_code = 0x2; | ||
| 442 | mb_len = 3; | ||
| 443 | break; | ||
| 444 | case BFRAME_BIDIR: | ||
| 445 | mb_code = 0x2; | ||
| 446 | mb_len = 2; | ||
| 447 | break; | ||
| 448 | default: /* keep the compiler happy */ | ||
| 449 | mb_code = mb_len = 0; | ||
| 450 | break; | ||
| 451 | } | ||
| 452 | |||
| 453 | CODE_ADD(c, frame == PFRAME ? 0x2 : 0x3, 13); | ||
| 454 | CODE_ADD(c, 0xffff, 16); | ||
| 455 | CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4); | ||
| 456 | if (frame != PFRAME) | ||
| 457 | CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 0x7 : 0x4, 4); | ||
| 458 | else | ||
| 459 | CODE_ADD(c, 0, 4); /* Is this supposed to be here?? */ | ||
| 460 | CODE_ADD(c, 0, 3); /* What is this?? */ | ||
| 461 | /* Byte-align with zeros */ | ||
| 462 | j = 8 - (CODE_LENGTH(c) % 8); | ||
| 463 | if (j != 8) | ||
| 464 | CODE_ADD(c, 0, j); | ||
| 465 | |||
| 466 | if (go->format == V4L2_PIX_FMT_MPEG2) { | ||
| 467 | CODE_ADD(c, 0x1, 24); | ||
| 468 | CODE_ADD(c, 0xb5, 8); | ||
| 469 | CODE_ADD(c, 0x844, 12); | ||
| 470 | CODE_ADD(c, frame == PFRAME ? 0xff : 0x44, 8); | ||
| 471 | if (go->interlace_coding) { | ||
| 472 | CODE_ADD(c, pict_struct, 4); | ||
| 473 | if (go->dvd_mode) | ||
| 474 | CODE_ADD(c, 0x000, 11); | ||
| 475 | else | ||
| 476 | CODE_ADD(c, 0x200, 11); | ||
| 477 | } else { | ||
| 478 | CODE_ADD(c, 0x3, 4); | ||
| 479 | CODE_ADD(c, 0x20c, 11); | ||
| 480 | } | ||
| 481 | /* Byte-align with zeros */ | ||
| 482 | j = 8 - (CODE_LENGTH(c) % 8); | ||
| 483 | if (j != 8) | ||
| 484 | CODE_ADD(c, 0, j); | ||
| 485 | } | ||
| 486 | |||
| 487 | for (i = 0; i < rows; ++i) { | ||
| 488 | CODE_ADD(c, 1, 24); | ||
| 489 | CODE_ADD(c, i + 1, 8); | ||
| 490 | CODE_ADD(c, 0x2, 6); | ||
| 491 | CODE_ADD(c, 0x1, 1); | ||
| 492 | CODE_ADD(c, mb_code, mb_len); | ||
| 493 | if (go->interlace_coding) { | ||
| 494 | CODE_ADD(c, 0x1, 2); | ||
| 495 | CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); | ||
| 496 | } | ||
| 497 | if (frame == BFRAME_BIDIR) { | ||
| 498 | CODE_ADD(c, 0x3, 2); | ||
| 499 | if (go->interlace_coding) | ||
| 500 | CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); | ||
| 501 | } | ||
| 502 | CODE_ADD(c, 0x3, 2); | ||
| 503 | for (j = (go->width >> 4) - 2; j >= 33; j -= 33) | ||
| 504 | CODE_ADD(c, 0x8, 11); | ||
| 505 | CODE_ADD(c, addrinctab[j][0], addrinctab[j][1]); | ||
| 506 | CODE_ADD(c, mb_code, mb_len); | ||
| 507 | if (go->interlace_coding) { | ||
| 508 | CODE_ADD(c, 0x1, 2); | ||
| 509 | CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); | ||
| 510 | } | ||
| 511 | if (frame == BFRAME_BIDIR) { | ||
| 512 | CODE_ADD(c, 0x3, 2); | ||
| 513 | if (go->interlace_coding) | ||
| 514 | CODE_ADD(c, pict_struct == 1 ? 0x0 : 0x1, 1); | ||
| 515 | } | ||
| 516 | CODE_ADD(c, 0x3, 2); | ||
| 517 | |||
| 518 | /* Byte-align with zeros */ | ||
| 519 | j = 8 - (CODE_LENGTH(c) % 8); | ||
| 520 | if (j != 8) | ||
| 521 | CODE_ADD(c, 0, j); | ||
| 522 | } | ||
| 523 | |||
| 524 | i = CODE_LENGTH(c) + 4 * 8; | ||
| 525 | buf[2] = 0x00; | ||
| 526 | buf[3] = 0x00; | ||
| 527 | buf[4] = 0x01; | ||
| 528 | buf[5] = 0x00; | ||
| 529 | return i; | ||
| 530 | } | ||
| 531 | |||
| 532 | static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext) | ||
| 533 | { | ||
| 534 | int i, aspect_ratio, picture_rate; | ||
| 535 | CODE_GEN(c, buf + 6); | ||
| 536 | |||
| 537 | if (go->format == V4L2_PIX_FMT_MPEG1) { | ||
| 538 | switch (go->aspect_ratio) { | ||
| 539 | case GO7007_RATIO_4_3: | ||
| 540 | aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; | ||
| 541 | break; | ||
| 542 | case GO7007_RATIO_16_9: | ||
| 543 | aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; | ||
| 544 | break; | ||
| 545 | default: | ||
| 546 | aspect_ratio = 1; | ||
| 547 | break; | ||
| 548 | } | ||
| 549 | } else { | ||
| 550 | switch (go->aspect_ratio) { | ||
| 551 | case GO7007_RATIO_4_3: | ||
| 552 | aspect_ratio = 2; | ||
| 553 | break; | ||
| 554 | case GO7007_RATIO_16_9: | ||
| 555 | aspect_ratio = 3; | ||
| 556 | break; | ||
| 557 | default: | ||
| 558 | aspect_ratio = 1; | ||
| 559 | break; | ||
| 560 | } | ||
| 561 | } | ||
| 562 | switch (go->sensor_framerate) { | ||
| 563 | case 24000: | ||
| 564 | picture_rate = 1; | ||
| 565 | break; | ||
| 566 | case 24024: | ||
| 567 | picture_rate = 2; | ||
| 568 | break; | ||
| 569 | case 25025: | ||
| 570 | picture_rate = go->interlace_coding ? 6 : 3; | ||
| 571 | break; | ||
| 572 | case 30000: | ||
| 573 | picture_rate = go->interlace_coding ? 7 : 4; | ||
| 574 | break; | ||
| 575 | case 30030: | ||
| 576 | picture_rate = go->interlace_coding ? 8 : 5; | ||
| 577 | break; | ||
| 578 | default: | ||
| 579 | picture_rate = 5; /* 30 fps seems like a reasonable default */ | ||
| 580 | break; | ||
| 581 | } | ||
| 582 | |||
| 583 | CODE_ADD(c, go->width, 12); | ||
| 584 | CODE_ADD(c, go->height, 12); | ||
| 585 | CODE_ADD(c, aspect_ratio, 4); | ||
| 586 | CODE_ADD(c, picture_rate, 4); | ||
| 587 | CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 20000 : 0x3ffff, 18); | ||
| 588 | CODE_ADD(c, 1, 1); | ||
| 589 | CODE_ADD(c, go->format == V4L2_PIX_FMT_MPEG2 ? 112 : 20, 10); | ||
| 590 | CODE_ADD(c, 0, 3); | ||
| 591 | |||
| 592 | /* Byte-align with zeros */ | ||
| 593 | i = 8 - (CODE_LENGTH(c) % 8); | ||
| 594 | if (i != 8) | ||
| 595 | CODE_ADD(c, 0, i); | ||
| 596 | |||
| 597 | if (go->format == V4L2_PIX_FMT_MPEG2) { | ||
| 598 | CODE_ADD(c, 0x1, 24); | ||
| 599 | CODE_ADD(c, 0xb5, 8); | ||
| 600 | CODE_ADD(c, 0x148, 12); | ||
| 601 | if (go->interlace_coding) | ||
| 602 | CODE_ADD(c, 0x20001, 20); | ||
| 603 | else | ||
| 604 | CODE_ADD(c, 0xa0001, 20); | ||
| 605 | CODE_ADD(c, 0, 16); | ||
| 606 | |||
| 607 | /* Byte-align with zeros */ | ||
| 608 | i = 8 - (CODE_LENGTH(c) % 8); | ||
| 609 | if (i != 8) | ||
| 610 | CODE_ADD(c, 0, i); | ||
| 611 | |||
| 612 | if (ext) { | ||
| 613 | CODE_ADD(c, 0x1, 24); | ||
| 614 | CODE_ADD(c, 0xb52, 12); | ||
| 615 | CODE_ADD(c, go->standard == GO7007_STD_NTSC ? 2 : 1, 3); | ||
| 616 | CODE_ADD(c, 0x105, 9); | ||
| 617 | CODE_ADD(c, 0x505, 16); | ||
| 618 | CODE_ADD(c, go->width, 14); | ||
| 619 | CODE_ADD(c, 1, 1); | ||
| 620 | CODE_ADD(c, go->height, 14); | ||
| 621 | |||
| 622 | /* Byte-align with zeros */ | ||
| 623 | i = 8 - (CODE_LENGTH(c) % 8); | ||
| 624 | if (i != 8) | ||
| 625 | CODE_ADD(c, 0, i); | ||
| 626 | } | ||
| 627 | } | ||
| 628 | |||
| 629 | i = CODE_LENGTH(c) + 4 * 8; | ||
| 630 | buf[0] = i & 0xff; | ||
| 631 | buf[1] = i >> 8; | ||
| 632 | buf[2] = 0x00; | ||
| 633 | buf[3] = 0x00; | ||
| 634 | buf[4] = 0x01; | ||
| 635 | buf[5] = 0xb3; | ||
| 636 | return i; | ||
| 637 | } | ||
| 638 | |||
| 639 | static int gen_mpeg1hdr_to_package(struct go7007 *go, | ||
| 640 | __le16 *code, int space, int *framelen) | ||
| 641 | { | ||
| 642 | u8 *buf; | ||
| 643 | u16 mem = 0x3e00; | ||
| 644 | unsigned int addr = 0x19; | ||
| 645 | int i, off = 0, chunk; | ||
| 646 | |||
| 647 | buf = kzalloc(5120, GFP_KERNEL); | ||
| 648 | if (buf == NULL) | ||
| 649 | return -1; | ||
| 650 | |||
| 651 | framelen[0] = mpeg1_frame_header(go, buf, 0, 1, PFRAME); | ||
| 652 | if (go->interlace_coding) | ||
| 653 | framelen[0] += mpeg1_frame_header(go, buf + framelen[0] / 8, | ||
| 654 | 0, 2, PFRAME); | ||
| 655 | buf[0] = framelen[0] & 0xff; | ||
| 656 | buf[1] = framelen[0] >> 8; | ||
| 657 | i = 368; | ||
| 658 | framelen[1] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_PRE); | ||
| 659 | if (go->interlace_coding) | ||
| 660 | framelen[1] += mpeg1_frame_header(go, buf + i + framelen[1] / 8, | ||
| 661 | 0, 2, BFRAME_PRE); | ||
| 662 | buf[i] = framelen[1] & 0xff; | ||
| 663 | buf[i + 1] = framelen[1] >> 8; | ||
| 664 | i += 1632; | ||
| 665 | framelen[2] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_POST); | ||
| 666 | if (go->interlace_coding) | ||
| 667 | framelen[2] += mpeg1_frame_header(go, buf + i + framelen[2] / 8, | ||
| 668 | 0, 2, BFRAME_POST); | ||
| 669 | buf[i] = framelen[2] & 0xff; | ||
| 670 | buf[i + 1] = framelen[2] >> 8; | ||
| 671 | i += 1432; | ||
| 672 | framelen[3] = mpeg1_frame_header(go, buf + i, 0, 1, BFRAME_BIDIR); | ||
| 673 | if (go->interlace_coding) | ||
| 674 | framelen[3] += mpeg1_frame_header(go, buf + i + framelen[3] / 8, | ||
| 675 | 0, 2, BFRAME_BIDIR); | ||
| 676 | buf[i] = framelen[3] & 0xff; | ||
| 677 | buf[i + 1] = framelen[3] >> 8; | ||
| 678 | i += 1632 + 16; | ||
| 679 | mpeg1_sequence_header(go, buf + i, 0); | ||
| 680 | i += 40; | ||
| 681 | for (i = 0; i < 5120; i += chunk * 2) { | ||
| 682 | if (space - off < 32) { | ||
| 683 | off = -1; | ||
| 684 | goto done; | ||
| 685 | } | ||
| 686 | |||
| 687 | code[off + 1] = __cpu_to_le16(0x8000 | mem); | ||
| 688 | |||
| 689 | chunk = 28; | ||
| 690 | if (mem + chunk > 0x4000) | ||
| 691 | chunk = 0x4000 - mem; | ||
| 692 | if (i + 2 * chunk > 5120) | ||
| 693 | chunk = (5120 - i) / 2; | ||
| 694 | |||
| 695 | if (chunk < 28) { | ||
| 696 | code[off] = __cpu_to_le16(0x4000 | chunk); | ||
| 697 | code[off + 31] = __cpu_to_le16(addr); | ||
| 698 | if (mem + chunk == 0x4000) { | ||
| 699 | mem = 0x3e00; | ||
| 700 | ++addr; | ||
| 701 | } | ||
| 702 | } else { | ||
| 703 | code[off] = __cpu_to_le16(0x1000 | 28); | ||
| 704 | code[off + 31] = 0; | ||
| 705 | mem += 28; | ||
| 706 | } | ||
| 707 | |||
| 708 | memcpy(&code[off + 2], buf + i, chunk * 2); | ||
| 709 | off += 32; | ||
| 710 | } | ||
| 711 | done: | ||
| 712 | kfree(buf); | ||
| 713 | return off; | ||
| 714 | } | ||
| 715 | |||
| 716 | static int vti_bitlen(struct go7007 *go) | ||
| 717 | { | ||
| 718 | unsigned int i, max_time_incr = go->sensor_framerate / go->fps_scale; | ||
| 719 | |||
| 720 | for (i = 31; (max_time_incr & ((1 << i) - 1)) == max_time_incr; --i) | ||
| 721 | ; | ||
| 722 | return i + 1; | ||
| 723 | } | ||
| 724 | |||
| 725 | static int mpeg4_frame_header(struct go7007 *go, unsigned char *buf, | ||
| 726 | int modulo, enum mpeg_frame_type frame) | ||
| 727 | { | ||
| 728 | int i; | ||
| 729 | CODE_GEN(c, buf + 6); | ||
| 730 | int mb_count = (go->width >> 4) * (go->height >> 4); | ||
| 731 | |||
| 732 | CODE_ADD(c, frame == PFRAME ? 0x1 : 0x2, 2); | ||
| 733 | if (modulo) | ||
| 734 | CODE_ADD(c, 0x1, 1); | ||
| 735 | CODE_ADD(c, 0x1, 2); | ||
| 736 | CODE_ADD(c, 0, vti_bitlen(go)); | ||
| 737 | CODE_ADD(c, 0x3, 2); | ||
| 738 | if (frame == PFRAME) | ||
| 739 | CODE_ADD(c, 0, 1); | ||
| 740 | CODE_ADD(c, 0xc, 11); | ||
| 741 | if (frame != PFRAME) | ||
| 742 | CODE_ADD(c, 0x4, 3); | ||
| 743 | if (frame != BFRAME_EMPTY) { | ||
| 744 | for (i = 0; i < mb_count; ++i) { | ||
| 745 | switch (frame) { | ||
| 746 | case PFRAME: | ||
| 747 | CODE_ADD(c, 0x1, 1); | ||
| 748 | break; | ||
| 749 | case BFRAME_PRE: | ||
| 750 | CODE_ADD(c, 0x47, 8); | ||
| 751 | break; | ||
| 752 | case BFRAME_POST: | ||
| 753 | CODE_ADD(c, 0x27, 7); | ||
| 754 | break; | ||
| 755 | case BFRAME_BIDIR: | ||
| 756 | CODE_ADD(c, 0x5f, 8); | ||
| 757 | break; | ||
| 758 | case BFRAME_EMPTY: /* keep compiler quiet */ | ||
| 759 | break; | ||
| 760 | } | ||
| 761 | } | ||
| 762 | } | ||
| 763 | |||
| 764 | /* Byte-align with a zero followed by ones */ | ||
| 765 | i = 8 - (CODE_LENGTH(c) % 8); | ||
| 766 | CODE_ADD(c, 0, 1); | ||
| 767 | CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); | ||
| 768 | |||
| 769 | i = CODE_LENGTH(c) + 4 * 8; | ||
| 770 | buf[0] = i & 0xff; | ||
| 771 | buf[1] = i >> 8; | ||
| 772 | buf[2] = 0x00; | ||
| 773 | buf[3] = 0x00; | ||
| 774 | buf[4] = 0x01; | ||
| 775 | buf[5] = 0xb6; | ||
| 776 | return i; | ||
| 777 | } | ||
| 778 | |||
| 779 | static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext) | ||
| 780 | { | ||
| 781 | const unsigned char head[] = { 0x00, 0x00, 0x01, 0xb0, go->pali, | ||
| 782 | 0x00, 0x00, 0x01, 0xb5, 0x09, | ||
| 783 | 0x00, 0x00, 0x01, 0x00, | ||
| 784 | 0x00, 0x00, 0x01, 0x20, }; | ||
| 785 | int i, aspect_ratio; | ||
| 786 | int fps = go->sensor_framerate / go->fps_scale; | ||
| 787 | CODE_GEN(c, buf + 2 + sizeof(head)); | ||
| 788 | |||
| 789 | switch (go->aspect_ratio) { | ||
| 790 | case GO7007_RATIO_4_3: | ||
| 791 | aspect_ratio = go->standard == GO7007_STD_NTSC ? 3 : 2; | ||
| 792 | break; | ||
| 793 | case GO7007_RATIO_16_9: | ||
| 794 | aspect_ratio = go->standard == GO7007_STD_NTSC ? 5 : 4; | ||
| 795 | break; | ||
| 796 | default: | ||
| 797 | aspect_ratio = 1; | ||
| 798 | break; | ||
| 799 | } | ||
| 800 | |||
| 801 | memcpy(buf + 2, head, sizeof(head)); | ||
| 802 | CODE_ADD(c, 0x191, 17); | ||
| 803 | CODE_ADD(c, aspect_ratio, 4); | ||
| 804 | CODE_ADD(c, 0x1, 4); | ||
| 805 | CODE_ADD(c, fps, 16); | ||
| 806 | CODE_ADD(c, 0x3, 2); | ||
| 807 | CODE_ADD(c, 1001, vti_bitlen(go)); | ||
| 808 | CODE_ADD(c, 1, 1); | ||
| 809 | CODE_ADD(c, go->width, 13); | ||
| 810 | CODE_ADD(c, 1, 1); | ||
| 811 | CODE_ADD(c, go->height, 13); | ||
| 812 | CODE_ADD(c, 0x2830, 14); | ||
| 813 | |||
| 814 | /* Byte-align */ | ||
| 815 | i = 8 - (CODE_LENGTH(c) % 8); | ||
| 816 | CODE_ADD(c, 0, 1); | ||
| 817 | CODE_ADD(c, (1 << (i - 1)) - 1, i - 1); | ||
| 818 | |||
| 819 | i = CODE_LENGTH(c) + sizeof(head) * 8; | ||
| 820 | buf[0] = i & 0xff; | ||
| 821 | buf[1] = i >> 8; | ||
| 822 | return i; | ||
| 823 | } | ||
| 824 | |||
| 825 | static int gen_mpeg4hdr_to_package(struct go7007 *go, | ||
| 826 | __le16 *code, int space, int *framelen) | ||
| 827 | { | ||
| 828 | u8 *buf; | ||
| 829 | u16 mem = 0x3e00; | ||
| 830 | unsigned int addr = 0x19; | ||
| 831 | int i, off = 0, chunk; | ||
| 832 | |||
| 833 | buf = kzalloc(5120, GFP_KERNEL); | ||
| 834 | if (buf == NULL) | ||
| 835 | return -1; | ||
| 836 | |||
| 837 | framelen[0] = mpeg4_frame_header(go, buf, 0, PFRAME); | ||
| 838 | i = 368; | ||
| 839 | framelen[1] = mpeg4_frame_header(go, buf + i, 0, BFRAME_PRE); | ||
| 840 | i += 1632; | ||
| 841 | framelen[2] = mpeg4_frame_header(go, buf + i, 0, BFRAME_POST); | ||
| 842 | i += 1432; | ||
| 843 | framelen[3] = mpeg4_frame_header(go, buf + i, 0, BFRAME_BIDIR); | ||
| 844 | i += 1632; | ||
| 845 | mpeg4_frame_header(go, buf + i, 0, BFRAME_EMPTY); | ||
| 846 | i += 16; | ||
| 847 | mpeg4_sequence_header(go, buf + i, 0); | ||
| 848 | i += 40; | ||
| 849 | for (i = 0; i < 5120; i += chunk * 2) { | ||
| 850 | if (space - off < 32) { | ||
| 851 | off = -1; | ||
| 852 | goto done; | ||
| 853 | } | ||
| 854 | |||
| 855 | code[off + 1] = __cpu_to_le16(0x8000 | mem); | ||
| 856 | |||
| 857 | chunk = 28; | ||
| 858 | if (mem + chunk > 0x4000) | ||
| 859 | chunk = 0x4000 - mem; | ||
| 860 | if (i + 2 * chunk > 5120) | ||
| 861 | chunk = (5120 - i) / 2; | ||
| 862 | |||
| 863 | if (chunk < 28) { | ||
| 864 | code[off] = __cpu_to_le16(0x4000 | chunk); | ||
| 865 | code[off + 31] = __cpu_to_le16(addr); | ||
| 866 | if (mem + chunk == 0x4000) { | ||
| 867 | mem = 0x3e00; | ||
| 868 | ++addr; | ||
| 869 | } | ||
| 870 | } else { | ||
| 871 | code[off] = __cpu_to_le16(0x1000 | 28); | ||
| 872 | code[off + 31] = 0; | ||
| 873 | mem += 28; | ||
| 874 | } | ||
| 875 | |||
| 876 | memcpy(&code[off + 2], buf + i, chunk * 2); | ||
| 877 | off += 32; | ||
| 878 | } | ||
| 879 | mem = 0x3e00; | ||
| 880 | addr = go->ipb ? 0x14f9 : 0x0af9; | ||
| 881 | memset(buf, 0, 5120); | ||
| 882 | framelen[4] = mpeg4_frame_header(go, buf, 1, PFRAME); | ||
| 883 | i = 368; | ||
| 884 | framelen[5] = mpeg4_frame_header(go, buf + i, 1, BFRAME_PRE); | ||
| 885 | i += 1632; | ||
| 886 | framelen[6] = mpeg4_frame_header(go, buf + i, 1, BFRAME_POST); | ||
| 887 | i += 1432; | ||
| 888 | framelen[7] = mpeg4_frame_header(go, buf + i, 1, BFRAME_BIDIR); | ||
| 889 | i += 1632; | ||
| 890 | mpeg4_frame_header(go, buf + i, 1, BFRAME_EMPTY); | ||
| 891 | i += 16; | ||
| 892 | for (i = 0; i < 5120; i += chunk * 2) { | ||
| 893 | if (space - off < 32) { | ||
| 894 | off = -1; | ||
| 895 | goto done; | ||
| 896 | } | ||
| 897 | |||
| 898 | code[off + 1] = __cpu_to_le16(0x8000 | mem); | ||
| 899 | |||
| 900 | chunk = 28; | ||
| 901 | if (mem + chunk > 0x4000) | ||
| 902 | chunk = 0x4000 - mem; | ||
| 903 | if (i + 2 * chunk > 5120) | ||
| 904 | chunk = (5120 - i) / 2; | ||
| 905 | |||
| 906 | if (chunk < 28) { | ||
| 907 | code[off] = __cpu_to_le16(0x4000 | chunk); | ||
| 908 | code[off + 31] = __cpu_to_le16(addr); | ||
| 909 | if (mem + chunk == 0x4000) { | ||
| 910 | mem = 0x3e00; | ||
| 911 | ++addr; | ||
| 912 | } | ||
| 913 | } else { | ||
| 914 | code[off] = __cpu_to_le16(0x1000 | 28); | ||
| 915 | code[off + 31] = 0; | ||
| 916 | mem += 28; | ||
| 917 | } | ||
| 918 | |||
| 919 | memcpy(&code[off + 2], buf + i, chunk * 2); | ||
| 920 | off += 32; | ||
| 921 | } | ||
| 922 | done: | ||
| 923 | kfree(buf); | ||
| 924 | return off; | ||
| 925 | } | ||
| 926 | |||
| 927 | static int brctrl_to_package(struct go7007 *go, | ||
| 928 | __le16 *code, int space, int *framelen) | ||
| 929 | { | ||
| 930 | int converge_speed = 0; | ||
| 931 | int lambda = (go->format == V4L2_PIX_FMT_MJPEG || go->dvd_mode) ? | ||
| 932 | 100 : 0; | ||
| 933 | int peak_rate = 6 * go->bitrate / 5; | ||
| 934 | int vbv_buffer = go->format == V4L2_PIX_FMT_MJPEG ? | ||
| 935 | go->bitrate : | ||
| 936 | (go->dvd_mode ? 900000 : peak_rate); | ||
| 937 | int fps = go->sensor_framerate / go->fps_scale; | ||
| 938 | int q = 0; | ||
| 939 | /* Bizarre math below depends on rounding errors in division */ | ||
| 940 | u32 sgop_expt_addr = go->bitrate / 32 * (go->ipb ? 3 : 1) * 1001 / fps; | ||
| 941 | u32 sgop_peak_addr = peak_rate / 32 * 1001 / fps; | ||
| 942 | u32 total_expt_addr = go->bitrate / 32 * 1000 / fps * (fps / 1000); | ||
| 943 | u32 vbv_alert_addr = vbv_buffer * 3 / (4 * 32); | ||
| 944 | u32 cplx[] = { | ||
| 945 | q > 0 ? sgop_expt_addr * q : | ||
| 946 | 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, | ||
| 947 | q > 0 ? sgop_expt_addr * q : | ||
| 948 | 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, | ||
| 949 | q > 0 ? sgop_expt_addr * q : | ||
| 950 | 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, | ||
| 951 | q > 0 ? sgop_expt_addr * q : | ||
| 952 | 2 * go->width * go->height * (go->ipb ? 6 : 4) / 32, | ||
| 953 | }; | ||
| 954 | u32 calc_q = q > 0 ? q : cplx[0] / sgop_expt_addr; | ||
| 955 | u16 pack[] = { | ||
| 956 | 0x200e, 0x0000, | ||
| 957 | 0xBF20, go->ipb ? converge_speed_ipb[converge_speed] | ||
| 958 | : converge_speed_ip[converge_speed], | ||
| 959 | 0xBF21, go->ipb ? 2 : 0, | ||
| 960 | 0xBF22, go->ipb ? LAMBDA_table[0][lambda / 2 + 50] | ||
| 961 | : 32767, | ||
| 962 | 0xBF23, go->ipb ? LAMBDA_table[1][lambda] : 32767, | ||
| 963 | 0xBF24, 32767, | ||
| 964 | 0xBF25, lambda > 99 ? 32767 : LAMBDA_table[3][lambda], | ||
| 965 | 0xBF26, sgop_expt_addr & 0x0000FFFF, | ||
| 966 | 0xBF27, sgop_expt_addr >> 16, | ||
| 967 | 0xBF28, sgop_peak_addr & 0x0000FFFF, | ||
| 968 | 0xBF29, sgop_peak_addr >> 16, | ||
| 969 | 0xBF2A, vbv_alert_addr & 0x0000FFFF, | ||
| 970 | 0xBF2B, vbv_alert_addr >> 16, | ||
| 971 | 0xBF2C, 0, | ||
| 972 | 0xBF2D, 0, | ||
| 973 | 0, 0, | ||
| 974 | |||
| 975 | 0x200e, 0x0000, | ||
| 976 | 0xBF2E, vbv_alert_addr & 0x0000FFFF, | ||
| 977 | 0xBF2F, vbv_alert_addr >> 16, | ||
| 978 | 0xBF30, cplx[0] & 0x0000FFFF, | ||
| 979 | 0xBF31, cplx[0] >> 16, | ||
| 980 | 0xBF32, cplx[1] & 0x0000FFFF, | ||
| 981 | 0xBF33, cplx[1] >> 16, | ||
| 982 | 0xBF34, cplx[2] & 0x0000FFFF, | ||
| 983 | 0xBF35, cplx[2] >> 16, | ||
| 984 | 0xBF36, cplx[3] & 0x0000FFFF, | ||
| 985 | 0xBF37, cplx[3] >> 16, | ||
| 986 | 0xBF38, 0, | ||
| 987 | 0xBF39, 0, | ||
| 988 | 0xBF3A, total_expt_addr & 0x0000FFFF, | ||
| 989 | 0xBF3B, total_expt_addr >> 16, | ||
| 990 | 0, 0, | ||
| 991 | |||
| 992 | 0x200e, 0x0000, | ||
| 993 | 0xBF3C, total_expt_addr & 0x0000FFFF, | ||
| 994 | 0xBF3D, total_expt_addr >> 16, | ||
| 995 | 0xBF3E, 0, | ||
| 996 | 0xBF3F, 0, | ||
| 997 | 0xBF48, 0, | ||
| 998 | 0xBF49, 0, | ||
| 999 | 0xBF4A, calc_q < 4 ? 4 : (calc_q > 124 ? 124 : calc_q), | ||
| 1000 | 0xBF4B, 4, | ||
| 1001 | 0xBF4C, 0, | ||
| 1002 | 0xBF4D, 0, | ||
| 1003 | 0xBF4E, 0, | ||
| 1004 | 0xBF4F, 0, | ||
| 1005 | 0xBF50, 0, | ||
| 1006 | 0xBF51, 0, | ||
| 1007 | 0, 0, | ||
| 1008 | |||
| 1009 | 0x200e, 0x0000, | ||
| 1010 | 0xBF40, sgop_expt_addr & 0x0000FFFF, | ||
| 1011 | 0xBF41, sgop_expt_addr >> 16, | ||
| 1012 | 0xBF42, 0, | ||
| 1013 | 0xBF43, 0, | ||
| 1014 | 0xBF44, 0, | ||
| 1015 | 0xBF45, 0, | ||
| 1016 | 0xBF46, (go->width >> 4) * (go->height >> 4), | ||
| 1017 | 0xBF47, 0, | ||
| 1018 | 0xBF64, 0, | ||
| 1019 | 0xBF65, 0, | ||
| 1020 | 0xBF18, framelen[4], | ||
| 1021 | 0xBF19, framelen[5], | ||
| 1022 | 0xBF1A, framelen[6], | ||
| 1023 | 0xBF1B, framelen[7], | ||
| 1024 | 0, 0, | ||
| 1025 | |||
| 1026 | #if 0 | ||
| 1027 | /* Remove once we don't care about matching */ | ||
| 1028 | 0x200e, 0x0000, | ||
| 1029 | 0xBF56, 4, | ||
| 1030 | 0xBF57, 0, | ||
| 1031 | 0xBF58, 5, | ||
| 1032 | 0xBF59, 0, | ||
| 1033 | 0xBF5A, 6, | ||
| 1034 | 0xBF5B, 0, | ||
| 1035 | 0xBF5C, 8, | ||
| 1036 | 0xBF5D, 0, | ||
| 1037 | 0xBF5E, 1, | ||
| 1038 | 0xBF5F, 0, | ||
| 1039 | 0xBF60, 1, | ||
| 1040 | 0xBF61, 0, | ||
| 1041 | 0xBF62, 0, | ||
| 1042 | 0xBF63, 0, | ||
| 1043 | 0, 0, | ||
| 1044 | #else | ||
| 1045 | 0x2008, 0x0000, | ||
| 1046 | 0xBF56, 4, | ||
| 1047 | 0xBF57, 0, | ||
| 1048 | 0xBF58, 5, | ||
| 1049 | 0xBF59, 0, | ||
| 1050 | 0xBF5A, 6, | ||
| 1051 | 0xBF5B, 0, | ||
| 1052 | 0xBF5C, 8, | ||
| 1053 | 0xBF5D, 0, | ||
| 1054 | 0, 0, | ||
| 1055 | 0, 0, | ||
| 1056 | 0, 0, | ||
| 1057 | 0, 0, | ||
| 1058 | 0, 0, | ||
| 1059 | 0, 0, | ||
| 1060 | 0, 0, | ||
| 1061 | #endif | ||
| 1062 | |||
| 1063 | 0x200e, 0x0000, | ||
| 1064 | 0xBF10, 0, | ||
| 1065 | 0xBF11, 0, | ||
| 1066 | 0xBF12, 0, | ||
| 1067 | 0xBF13, 0, | ||
| 1068 | 0xBF14, 0, | ||
| 1069 | 0xBF15, 0, | ||
| 1070 | 0xBF16, 0, | ||
| 1071 | 0xBF17, 0, | ||
| 1072 | 0xBF7E, 0, | ||
| 1073 | 0xBF7F, 1, | ||
| 1074 | 0xBF52, framelen[0], | ||
| 1075 | 0xBF53, framelen[1], | ||
| 1076 | 0xBF54, framelen[2], | ||
| 1077 | 0xBF55, framelen[3], | ||
| 1078 | 0, 0, | ||
| 1079 | }; | ||
| 1080 | |||
| 1081 | return copy_packages(code, pack, 6, space); | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | static int config_package(struct go7007 *go, __le16 *code, int space) | ||
| 1085 | { | ||
| 1086 | int fps = go->sensor_framerate / go->fps_scale / 1000; | ||
| 1087 | int rows = go->interlace_coding ? go->height / 32 : go->height / 16; | ||
| 1088 | int brc_window_size = fps; | ||
| 1089 | int q_min = 2, q_max = 31; | ||
| 1090 | int THACCoeffSet0 = 0; | ||
| 1091 | u16 pack[] = { | ||
| 1092 | 0x200e, 0x0000, | ||
| 1093 | 0xc002, 0x14b4, | ||
| 1094 | 0xc003, 0x28b4, | ||
| 1095 | 0xc004, 0x3c5a, | ||
| 1096 | 0xdc05, 0x2a77, | ||
| 1097 | 0xc6c3, go->format == V4L2_PIX_FMT_MPEG4 ? 0 : | ||
| 1098 | (go->format == V4L2_PIX_FMT_H263 ? 0 : 1), | ||
| 1099 | 0xc680, go->format == V4L2_PIX_FMT_MPEG4 ? 0xf1 : | ||
| 1100 | (go->format == V4L2_PIX_FMT_H263 ? 0x61 : | ||
| 1101 | 0xd3), | ||
| 1102 | 0xc780, 0x0140, | ||
| 1103 | 0xe009, 0x0001, | ||
| 1104 | 0xc60f, 0x0008, | ||
| 1105 | 0xd4ff, 0x0002, | ||
| 1106 | 0xe403, 2340, | ||
| 1107 | 0xe406, 75, | ||
| 1108 | 0xd411, 0x0001, | ||
| 1109 | 0xd410, 0xa1d6, | ||
| 1110 | 0x0001, 0x2801, | ||
| 1111 | |||
| 1112 | 0x200d, 0x0000, | ||
| 1113 | 0xe402, 0x018b, | ||
| 1114 | 0xe401, 0x8b01, | ||
| 1115 | 0xd472, (go->board_info->sensor_flags & | ||
| 1116 | GO7007_SENSOR_TV) && | ||
| 1117 | (!go->interlace_coding) ? | ||
| 1118 | 0x01b0 : 0x0170, | ||
| 1119 | 0xd475, (go->board_info->sensor_flags & | ||
| 1120 | GO7007_SENSOR_TV) && | ||
| 1121 | (!go->interlace_coding) ? | ||
| 1122 | 0x0008 : 0x0009, | ||
| 1123 | 0xc404, go->interlace_coding ? 0x44 : | ||
| 1124 | (go->format == V4L2_PIX_FMT_MPEG4 ? 0x11 : | ||
| 1125 | (go->format == V4L2_PIX_FMT_MPEG1 ? 0x02 : | ||
| 1126 | (go->format == V4L2_PIX_FMT_MPEG2 ? 0x04 : | ||
| 1127 | (go->format == V4L2_PIX_FMT_H263 ? 0x08 : | ||
| 1128 | 0x20)))), | ||
| 1129 | 0xbf0a, (go->format == V4L2_PIX_FMT_MPEG4 ? 8 : | ||
| 1130 | (go->format == V4L2_PIX_FMT_MPEG1 ? 1 : | ||
| 1131 | (go->format == V4L2_PIX_FMT_MPEG2 ? 2 : | ||
| 1132 | (go->format == V4L2_PIX_FMT_H263 ? 4 : 16)))) | | ||
| 1133 | ((go->repeat_seqhead ? 1 : 0) << 6) | | ||
| 1134 | ((go->dvd_mode ? 1 : 0) << 9) | | ||
| 1135 | ((go->gop_header_enable ? 1 : 0) << 10), | ||
| 1136 | 0xbf0b, 0, | ||
| 1137 | 0xdd5a, go->ipb ? 0x14 : 0x0a, | ||
| 1138 | 0xbf0c, 0, | ||
| 1139 | 0xbf0d, 0, | ||
| 1140 | 0xc683, THACCoeffSet0, | ||
| 1141 | 0xc40a, (go->width << 4) | rows, | ||
| 1142 | 0xe01a, go->board_info->hpi_buffer_cap, | ||
| 1143 | 0, 0, | ||
| 1144 | 0, 0, | ||
| 1145 | |||
| 1146 | 0x2008, 0, | ||
| 1147 | 0xe402, 0x88, | ||
| 1148 | 0xe401, 0x8f01, | ||
| 1149 | 0xbf6a, 0, | ||
| 1150 | 0xbf6b, 0, | ||
| 1151 | 0xbf6c, 0, | ||
| 1152 | 0xbf6d, 0, | ||
| 1153 | 0xbf6e, 0, | ||
| 1154 | 0xbf6f, 0, | ||
| 1155 | 0, 0, | ||
| 1156 | 0, 0, | ||
| 1157 | 0, 0, | ||
| 1158 | 0, 0, | ||
| 1159 | 0, 0, | ||
| 1160 | 0, 0, | ||
| 1161 | 0, 0, | ||
| 1162 | |||
| 1163 | 0x200e, 0, | ||
| 1164 | 0xbf66, brc_window_size, | ||
| 1165 | 0xbf67, 0, | ||
| 1166 | 0xbf68, q_min, | ||
| 1167 | 0xbf69, q_max, | ||
| 1168 | 0xbfe0, 0, | ||
| 1169 | 0xbfe1, 0, | ||
| 1170 | 0xbfe2, 0, | ||
| 1171 | 0xbfe3, go->ipb ? 3 : 1, | ||
| 1172 | 0xc031, go->board_info->sensor_flags & | ||
| 1173 | GO7007_SENSOR_VBI ? 1 : 0, | ||
| 1174 | 0xc01c, 0x1f, | ||
| 1175 | 0xdd8c, 0x15, | ||
| 1176 | 0xdd94, 0x15, | ||
| 1177 | 0xdd88, go->ipb ? 0x1401 : 0x0a01, | ||
| 1178 | 0xdd90, go->ipb ? 0x1401 : 0x0a01, | ||
| 1179 | 0, 0, | ||
| 1180 | |||
| 1181 | 0x200e, 0, | ||
| 1182 | 0xbfe4, 0, | ||
| 1183 | 0xbfe5, 0, | ||
| 1184 | 0xbfe6, 0, | ||
| 1185 | 0xbfe7, fps << 8, | ||
| 1186 | 0xbfe8, 0x3a00, | ||
| 1187 | 0xbfe9, 0, | ||
| 1188 | 0xbfea, 0, | ||
| 1189 | 0xbfeb, 0, | ||
| 1190 | 0xbfec, (go->interlace_coding ? 1 << 15 : 0) | | ||
| 1191 | (go->modet_enable ? 0xa : 0) | | ||
| 1192 | (go->board_info->sensor_flags & | ||
| 1193 | GO7007_SENSOR_VBI ? 1 : 0), | ||
| 1194 | 0xbfed, 0, | ||
| 1195 | 0xbfee, 0, | ||
| 1196 | 0xbfef, 0, | ||
| 1197 | 0xbff0, go->board_info->sensor_flags & | ||
| 1198 | GO7007_SENSOR_TV ? 0xf060 : 0xb060, | ||
| 1199 | 0xbff1, 0, | ||
| 1200 | 0, 0, | ||
| 1201 | }; | ||
| 1202 | |||
| 1203 | return copy_packages(code, pack, 5, space); | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | static int seqhead_to_package(struct go7007 *go, __le16 *code, int space, | ||
| 1207 | int (*sequence_header_func)(struct go7007 *go, | ||
| 1208 | unsigned char *buf, int ext)) | ||
| 1209 | { | ||
| 1210 | int vop_time_increment_bitlength = vti_bitlen(go); | ||
| 1211 | int fps = go->sensor_framerate / go->fps_scale * | ||
| 1212 | (go->interlace_coding ? 2 : 1); | ||
| 1213 | unsigned char buf[40] = { }; | ||
| 1214 | int len = sequence_header_func(go, buf, 1); | ||
| 1215 | u16 pack[] = { | ||
| 1216 | 0x2006, 0, | ||
| 1217 | 0xbf08, fps, | ||
| 1218 | 0xbf09, 0, | ||
| 1219 | 0xbff2, vop_time_increment_bitlength, | ||
| 1220 | 0xbff3, (1 << vop_time_increment_bitlength) - 1, | ||
| 1221 | 0xbfe6, 0, | ||
| 1222 | 0xbfe7, (fps / 1000) << 8, | ||
| 1223 | 0, 0, | ||
| 1224 | 0, 0, | ||
| 1225 | 0, 0, | ||
| 1226 | 0, 0, | ||
| 1227 | 0, 0, | ||
| 1228 | 0, 0, | ||
| 1229 | 0, 0, | ||
| 1230 | 0, 0, | ||
| 1231 | 0, 0, | ||
| 1232 | |||
| 1233 | 0x2007, 0, | ||
| 1234 | 0xc800, buf[2] << 8 | buf[3], | ||
| 1235 | 0xc801, buf[4] << 8 | buf[5], | ||
| 1236 | 0xc802, buf[6] << 8 | buf[7], | ||
| 1237 | 0xc803, buf[8] << 8 | buf[9], | ||
| 1238 | 0xc406, 64, | ||
| 1239 | 0xc407, len - 64, | ||
| 1240 | 0xc61b, 1, | ||
| 1241 | 0, 0, | ||
| 1242 | 0, 0, | ||
| 1243 | 0, 0, | ||
| 1244 | 0, 0, | ||
| 1245 | 0, 0, | ||
| 1246 | 0, 0, | ||
| 1247 | 0, 0, | ||
| 1248 | 0, 0, | ||
| 1249 | |||
| 1250 | 0x200e, 0, | ||
| 1251 | 0xc808, buf[10] << 8 | buf[11], | ||
| 1252 | 0xc809, buf[12] << 8 | buf[13], | ||
| 1253 | 0xc80a, buf[14] << 8 | buf[15], | ||
| 1254 | 0xc80b, buf[16] << 8 | buf[17], | ||
| 1255 | 0xc80c, buf[18] << 8 | buf[19], | ||
| 1256 | 0xc80d, buf[20] << 8 | buf[21], | ||
| 1257 | 0xc80e, buf[22] << 8 | buf[23], | ||
| 1258 | 0xc80f, buf[24] << 8 | buf[25], | ||
| 1259 | 0xc810, buf[26] << 8 | buf[27], | ||
| 1260 | 0xc811, buf[28] << 8 | buf[29], | ||
| 1261 | 0xc812, buf[30] << 8 | buf[31], | ||
| 1262 | 0xc813, buf[32] << 8 | buf[33], | ||
| 1263 | 0xc814, buf[34] << 8 | buf[35], | ||
| 1264 | 0xc815, buf[36] << 8 | buf[37], | ||
| 1265 | 0, 0, | ||
| 1266 | 0, 0, | ||
| 1267 | 0, 0, | ||
| 1268 | }; | ||
| 1269 | |||
| 1270 | return copy_packages(code, pack, 3, space); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | static int relative_prime(int big, int little) | ||
| 1274 | { | ||
| 1275 | int remainder; | ||
| 1276 | |||
| 1277 | while (little != 0) { | ||
| 1278 | remainder = big % little; | ||
| 1279 | big = little; | ||
| 1280 | little = remainder; | ||
| 1281 | } | ||
| 1282 | return big; | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | static int avsync_to_package(struct go7007 *go, __le16 *code, int space) | ||
| 1286 | { | ||
| 1287 | int arate = go->board_info->audio_rate * 1001 * go->fps_scale; | ||
| 1288 | int ratio = arate / go->sensor_framerate; | ||
| 1289 | int adjratio = ratio * 215 / 100; | ||
| 1290 | int rprime = relative_prime(go->sensor_framerate, | ||
| 1291 | arate % go->sensor_framerate); | ||
| 1292 | int f1 = (arate % go->sensor_framerate) / rprime; | ||
| 1293 | int f2 = (go->sensor_framerate - arate % go->sensor_framerate) / rprime; | ||
| 1294 | u16 pack[] = { | ||
| 1295 | 0x200e, 0, | ||
| 1296 | 0xbf98, (u16)((-adjratio) & 0xffff), | ||
| 1297 | 0xbf99, (u16)((-adjratio) >> 16), | ||
| 1298 | 0xbf92, 0, | ||
| 1299 | 0xbf93, 0, | ||
| 1300 | 0xbff4, f1 > f2 ? f1 : f2, | ||
| 1301 | 0xbff5, f1 < f2 ? f1 : f2, | ||
| 1302 | 0xbff6, f1 < f2 ? ratio : ratio + 1, | ||
| 1303 | 0xbff7, f1 > f2 ? ratio : ratio + 1, | ||
| 1304 | 0xbff8, 0, | ||
| 1305 | 0xbff9, 0, | ||
| 1306 | 0xbffa, adjratio & 0xffff, | ||
| 1307 | 0xbffb, adjratio >> 16, | ||
| 1308 | 0xbf94, 0, | ||
| 1309 | 0xbf95, 0, | ||
| 1310 | 0, 0, | ||
| 1311 | }; | ||
| 1312 | |||
| 1313 | return copy_packages(code, pack, 1, space); | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | static int final_package(struct go7007 *go, __le16 *code, int space) | ||
| 1317 | { | ||
| 1318 | int rows = go->interlace_coding ? go->height / 32 : go->height / 16; | ||
| 1319 | u16 pack[] = { | ||
| 1320 | 0x8000, | ||
| 1321 | 0, | ||
| 1322 | 0, | ||
| 1323 | 0, | ||
| 1324 | 0, | ||
| 1325 | 0, | ||
| 1326 | 0, | ||
| 1327 | 2, | ||
| 1328 | ((go->board_info->sensor_flags & GO7007_SENSOR_TV) && | ||
| 1329 | (!go->interlace_coding) ? | ||
| 1330 | (1 << 14) | (1 << 9) : 0) | | ||
| 1331 | ((go->encoder_subsample ? 1 : 0) << 8) | | ||
| 1332 | (go->board_info->sensor_flags & | ||
| 1333 | GO7007_SENSOR_CONFIG_MASK), | ||
| 1334 | ((go->encoder_v_halve ? 1 : 0) << 14) | | ||
| 1335 | (go->encoder_v_halve ? rows << 9 : rows << 8) | | ||
| 1336 | (go->encoder_h_halve ? 1 << 6 : 0) | | ||
| 1337 | (go->encoder_h_halve ? go->width >> 3 : go->width >> 4), | ||
| 1338 | (1 << 15) | (go->encoder_v_offset << 6) | | ||
| 1339 | (1 << 7) | (go->encoder_h_offset >> 2), | ||
| 1340 | (1 << 6), | ||
| 1341 | 0, | ||
| 1342 | 0, | ||
| 1343 | ((go->fps_scale - 1) << 8) | | ||
| 1344 | (go->board_info->sensor_flags & GO7007_SENSOR_TV ? | ||
| 1345 | (1 << 7) : 0) | | ||
| 1346 | 0x41, | ||
| 1347 | go->ipb ? 0xd4c : 0x36b, | ||
| 1348 | (rows << 8) | (go->width >> 4), | ||
| 1349 | go->format == V4L2_PIX_FMT_MPEG4 ? 0x0404 : 0, | ||
| 1350 | (1 << 15) | ((go->interlace_coding ? 1 : 0) << 13) | | ||
| 1351 | ((go->closed_gop ? 1 : 0) << 12) | | ||
| 1352 | ((go->format == V4L2_PIX_FMT_MPEG4 ? 1 : 0) << 11) | | ||
| 1353 | /* (1 << 9) | */ | ||
| 1354 | ((go->ipb ? 3 : 0) << 7) | | ||
| 1355 | ((go->modet_enable ? 1 : 0) << 2) | | ||
| 1356 | ((go->dvd_mode ? 1 : 0) << 1) | 1, | ||
| 1357 | (go->format == V4L2_PIX_FMT_MPEG1 ? 0x89a0 : | ||
| 1358 | (go->format == V4L2_PIX_FMT_MPEG2 ? 0x89a0 : | ||
| 1359 | (go->format == V4L2_PIX_FMT_MJPEG ? 0x89a0 : | ||
| 1360 | (go->format == V4L2_PIX_FMT_MPEG4 ? 0x8920 : | ||
| 1361 | (go->format == V4L2_PIX_FMT_H263 ? 0x8920 : 0))))), | ||
| 1362 | go->ipb ? 0x1f15 : 0x1f0b, | ||
| 1363 | go->ipb ? 0x0015 : 0x000b, | ||
| 1364 | go->ipb ? 0xa800 : 0x5800, | ||
| 1365 | 0xffff, | ||
| 1366 | 0x0020 + 0x034b * 0, | ||
| 1367 | 0x0020 + 0x034b * 1, | ||
| 1368 | 0x0020 + 0x034b * 2, | ||
| 1369 | 0x0020 + 0x034b * 3, | ||
| 1370 | 0x0020 + 0x034b * 4, | ||
| 1371 | 0x0020 + 0x034b * 5, | ||
| 1372 | go->ipb ? (go->gop_size / 3) : go->gop_size, | ||
| 1373 | (go->height >> 4) * (go->width >> 4) * 110 / 100, | ||
| 1374 | }; | ||
| 1375 | |||
| 1376 | return copy_packages(code, pack, 1, space); | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | static int audio_to_package(struct go7007 *go, __le16 *code, int space) | ||
| 1380 | { | ||
| 1381 | int clock_config = ((go->board_info->audio_flags & | ||
| 1382 | GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) | | ||
| 1383 | ((go->board_info->audio_flags & | ||
| 1384 | GO7007_AUDIO_OKI_MODE ? 1 : 0) << 8) | | ||
| 1385 | (((go->board_info->audio_bclk_div / 4) - 1) << 4) | | ||
| 1386 | (go->board_info->audio_main_div - 1); | ||
| 1387 | u16 pack[] = { | ||
| 1388 | 0x200d, 0, | ||
| 1389 | 0x9002, 0, | ||
| 1390 | 0x9002, 0, | ||
| 1391 | 0x9031, 0, | ||
| 1392 | 0x9032, 0, | ||
| 1393 | 0x9033, 0, | ||
| 1394 | 0x9034, 0, | ||
| 1395 | 0x9035, 0, | ||
| 1396 | 0x9036, 0, | ||
| 1397 | 0x9037, 0, | ||
| 1398 | 0x9040, 0, | ||
| 1399 | 0x9000, clock_config, | ||
| 1400 | 0x9001, (go->board_info->audio_flags & 0xffff) | | ||
| 1401 | (1 << 9), | ||
| 1402 | 0x9000, ((go->board_info->audio_flags & | ||
| 1403 | GO7007_AUDIO_I2S_MASTER ? | ||
| 1404 | 1 : 0) << 10) | | ||
| 1405 | clock_config, | ||
| 1406 | 0, 0, | ||
| 1407 | 0, 0, | ||
| 1408 | 0x2005, 0, | ||
| 1409 | 0x9041, 0, | ||
| 1410 | 0x9042, 256, | ||
| 1411 | 0x9043, 0, | ||
| 1412 | 0x9044, 16, | ||
| 1413 | 0x9045, 16, | ||
| 1414 | 0, 0, | ||
| 1415 | 0, 0, | ||
| 1416 | 0, 0, | ||
| 1417 | 0, 0, | ||
| 1418 | 0, 0, | ||
| 1419 | 0, 0, | ||
| 1420 | 0, 0, | ||
| 1421 | 0, 0, | ||
| 1422 | 0, 0, | ||
| 1423 | 0, 0, | ||
| 1424 | }; | ||
| 1425 | |||
| 1426 | return copy_packages(code, pack, 2, space); | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static int modet_to_package(struct go7007 *go, __le16 *code, int space) | ||
| 1430 | { | ||
| 1431 | bool has_modet0 = go->modet[0].enable; | ||
| 1432 | bool has_modet1 = go->modet[1].enable; | ||
| 1433 | bool has_modet2 = go->modet[2].enable; | ||
| 1434 | bool has_modet3 = go->modet[3].enable; | ||
| 1435 | int ret, mb, i, addr, cnt = 0; | ||
| 1436 | u16 pack[32]; | ||
| 1437 | u16 thresholds[] = { | ||
| 1438 | 0x200e, 0, | ||
| 1439 | 0xbf82, has_modet0 ? go->modet[0].pixel_threshold : 32767, | ||
| 1440 | 0xbf83, has_modet1 ? go->modet[1].pixel_threshold : 32767, | ||
| 1441 | 0xbf84, has_modet2 ? go->modet[2].pixel_threshold : 32767, | ||
| 1442 | 0xbf85, has_modet3 ? go->modet[3].pixel_threshold : 32767, | ||
| 1443 | 0xbf86, has_modet0 ? go->modet[0].motion_threshold : 32767, | ||
| 1444 | 0xbf87, has_modet1 ? go->modet[1].motion_threshold : 32767, | ||
| 1445 | 0xbf88, has_modet2 ? go->modet[2].motion_threshold : 32767, | ||
| 1446 | 0xbf89, has_modet3 ? go->modet[3].motion_threshold : 32767, | ||
| 1447 | 0xbf8a, has_modet0 ? go->modet[0].mb_threshold : 32767, | ||
| 1448 | 0xbf8b, has_modet1 ? go->modet[1].mb_threshold : 32767, | ||
| 1449 | 0xbf8c, has_modet2 ? go->modet[2].mb_threshold : 32767, | ||
| 1450 | 0xbf8d, has_modet3 ? go->modet[3].mb_threshold : 32767, | ||
| 1451 | 0xbf8e, 0, | ||
| 1452 | 0xbf8f, 0, | ||
| 1453 | 0, 0, | ||
| 1454 | }; | ||
| 1455 | |||
| 1456 | ret = copy_packages(code, thresholds, 1, space); | ||
| 1457 | if (ret < 0) | ||
| 1458 | return -1; | ||
| 1459 | cnt += ret; | ||
| 1460 | |||
| 1461 | addr = 0xbac0; | ||
| 1462 | memset(pack, 0, 64); | ||
| 1463 | i = 0; | ||
| 1464 | for (mb = 0; mb < 1624; ++mb) { | ||
| 1465 | pack[i * 2 + 3] <<= 2; | ||
| 1466 | pack[i * 2 + 3] |= go->modet_map[mb]; | ||
| 1467 | if (mb % 8 != 7) | ||
| 1468 | continue; | ||
| 1469 | pack[i * 2 + 2] = addr++; | ||
| 1470 | ++i; | ||
| 1471 | if (i == 10 || mb == 1623) { | ||
| 1472 | pack[0] = 0x2000 | i; | ||
| 1473 | ret = copy_packages(code + cnt, pack, 1, space - cnt); | ||
| 1474 | if (ret < 0) | ||
| 1475 | return -1; | ||
| 1476 | cnt += ret; | ||
| 1477 | i = 0; | ||
| 1478 | memset(pack, 0, 64); | ||
| 1479 | } | ||
| 1480 | pack[i * 2 + 3] = 0; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | memset(pack, 0, 64); | ||
| 1484 | i = 0; | ||
| 1485 | for (addr = 0xbb90; addr < 0xbbfa; ++addr) { | ||
| 1486 | pack[i * 2 + 2] = addr; | ||
| 1487 | pack[i * 2 + 3] = 0; | ||
| 1488 | ++i; | ||
| 1489 | if (i == 10 || addr == 0xbbf9) { | ||
| 1490 | pack[0] = 0x2000 | i; | ||
| 1491 | ret = copy_packages(code + cnt, pack, 1, space - cnt); | ||
| 1492 | if (ret < 0) | ||
| 1493 | return -1; | ||
| 1494 | cnt += ret; | ||
| 1495 | i = 0; | ||
| 1496 | memset(pack, 0, 64); | ||
| 1497 | } | ||
| 1498 | } | ||
| 1499 | return cnt; | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | static int do_special(struct go7007 *go, u16 type, __le16 *code, int space, | ||
| 1503 | int *framelen) | ||
| 1504 | { | ||
| 1505 | switch (type) { | ||
| 1506 | case SPECIAL_FRM_HEAD: | ||
| 1507 | switch (go->format) { | ||
| 1508 | case V4L2_PIX_FMT_MJPEG: | ||
| 1509 | return gen_mjpeghdr_to_package(go, code, space); | ||
| 1510 | case V4L2_PIX_FMT_MPEG1: | ||
| 1511 | case V4L2_PIX_FMT_MPEG2: | ||
| 1512 | return gen_mpeg1hdr_to_package(go, code, space, | ||
| 1513 | framelen); | ||
| 1514 | case V4L2_PIX_FMT_MPEG4: | ||
| 1515 | return gen_mpeg4hdr_to_package(go, code, space, | ||
| 1516 | framelen); | ||
| 1517 | } | ||
| 1518 | case SPECIAL_BRC_CTRL: | ||
| 1519 | return brctrl_to_package(go, code, space, framelen); | ||
| 1520 | case SPECIAL_CONFIG: | ||
| 1521 | return config_package(go, code, space); | ||
| 1522 | case SPECIAL_SEQHEAD: | ||
| 1523 | switch (go->format) { | ||
| 1524 | case V4L2_PIX_FMT_MPEG1: | ||
| 1525 | case V4L2_PIX_FMT_MPEG2: | ||
| 1526 | return seqhead_to_package(go, code, space, | ||
| 1527 | mpeg1_sequence_header); | ||
| 1528 | case V4L2_PIX_FMT_MPEG4: | ||
| 1529 | return seqhead_to_package(go, code, space, | ||
| 1530 | mpeg4_sequence_header); | ||
| 1531 | default: | ||
| 1532 | return 0; | ||
| 1533 | } | ||
| 1534 | case SPECIAL_AV_SYNC: | ||
| 1535 | return avsync_to_package(go, code, space); | ||
| 1536 | case SPECIAL_FINAL: | ||
| 1537 | return final_package(go, code, space); | ||
| 1538 | case SPECIAL_AUDIO: | ||
| 1539 | return audio_to_package(go, code, space); | ||
| 1540 | case SPECIAL_MODET: | ||
| 1541 | return modet_to_package(go, code, space); | ||
| 1542 | } | ||
| 1543 | dev_err(go->dev, | ||
| 1544 | "firmware file contains unsupported feature %04x\n", type); | ||
| 1545 | return -1; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen) | ||
| 1549 | { | ||
| 1550 | const struct firmware *fw_entry; | ||
| 1551 | __le16 *code, *src; | ||
| 1552 | int framelen[8] = { }; /* holds the lengths of empty frame templates */ | ||
| 1553 | int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags; | ||
| 1554 | int mode_flag; | ||
| 1555 | int ret; | ||
| 1556 | |||
| 1557 | switch (go->format) { | ||
| 1558 | case V4L2_PIX_FMT_MJPEG: | ||
| 1559 | mode_flag = FLAG_MODE_MJPEG; | ||
| 1560 | break; | ||
| 1561 | case V4L2_PIX_FMT_MPEG1: | ||
| 1562 | mode_flag = FLAG_MODE_MPEG1; | ||
| 1563 | break; | ||
| 1564 | case V4L2_PIX_FMT_MPEG2: | ||
| 1565 | mode_flag = FLAG_MODE_MPEG2; | ||
| 1566 | break; | ||
| 1567 | case V4L2_PIX_FMT_MPEG4: | ||
| 1568 | mode_flag = FLAG_MODE_MPEG4; | ||
| 1569 | break; | ||
| 1570 | default: | ||
| 1571 | return -1; | ||
| 1572 | } | ||
| 1573 | if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) { | ||
| 1574 | dev_err(go->dev, | ||
| 1575 | "unable to load firmware from file \"%s\"\n", | ||
| 1576 | GO7007_FW_NAME); | ||
| 1577 | return -1; | ||
| 1578 | } | ||
| 1579 | code = kzalloc(codespace * 2, GFP_KERNEL); | ||
| 1580 | if (code == NULL) | ||
| 1581 | goto fw_failed; | ||
| 1582 | |||
| 1583 | src = (__le16 *)fw_entry->data; | ||
| 1584 | srclen = fw_entry->size / 2; | ||
| 1585 | while (srclen >= 2) { | ||
| 1586 | chunk_flags = __le16_to_cpu(src[0]); | ||
| 1587 | chunk_len = __le16_to_cpu(src[1]); | ||
| 1588 | if (chunk_len + 2 > srclen) { | ||
| 1589 | dev_err(go->dev, | ||
| 1590 | "firmware file \"%s\" appears to be corrupted\n", | ||
| 1591 | GO7007_FW_NAME); | ||
| 1592 | goto fw_failed; | ||
| 1593 | } | ||
| 1594 | if (chunk_flags & mode_flag) { | ||
| 1595 | if (chunk_flags & FLAG_SPECIAL) { | ||
| 1596 | ret = do_special(go, __le16_to_cpu(src[2]), | ||
| 1597 | &code[i], codespace - i, framelen); | ||
| 1598 | if (ret < 0) { | ||
| 1599 | dev_err(go->dev, | ||
| 1600 | "insufficient memory for firmware construction\n"); | ||
| 1601 | goto fw_failed; | ||
| 1602 | } | ||
| 1603 | i += ret; | ||
| 1604 | } else { | ||
| 1605 | if (codespace - i < chunk_len) { | ||
| 1606 | dev_err(go->dev, | ||
| 1607 | "insufficient memory for firmware construction\n"); | ||
| 1608 | goto fw_failed; | ||
| 1609 | } | ||
| 1610 | memcpy(&code[i], &src[2], chunk_len * 2); | ||
| 1611 | i += chunk_len; | ||
| 1612 | } | ||
| 1613 | } | ||
| 1614 | srclen -= chunk_len + 2; | ||
| 1615 | src += chunk_len + 2; | ||
| 1616 | } | ||
| 1617 | release_firmware(fw_entry); | ||
| 1618 | *fw = (u8 *)code; | ||
| 1619 | *fwlen = i * 2; | ||
| 1620 | return 0; | ||
| 1621 | |||
| 1622 | fw_failed: | ||
| 1623 | kfree(code); | ||
| 1624 | release_firmware(fw_entry); | ||
| 1625 | return -1; | ||
| 1626 | } | ||
| 1627 | |||
| 1628 | MODULE_FIRMWARE(GO7007_FW_NAME); | ||
diff --git a/drivers/media/usb/go7007/go7007-i2c.c b/drivers/media/usb/go7007/go7007-i2c.c new file mode 100644 index 000000000000..55addfa855d4 --- /dev/null +++ b/drivers/media/usb/go7007/go7007-i2c.c | |||
| @@ -0,0 +1,218 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/list.h> | ||
| 18 | #include <linux/unistd.h> | ||
| 19 | #include <linux/time.h> | ||
| 20 | #include <linux/device.h> | ||
| 21 | #include <linux/i2c.h> | ||
| 22 | #include <linux/mutex.h> | ||
| 23 | #include <linux/uaccess.h> | ||
| 24 | |||
| 25 | #include "go7007-priv.h" | ||
| 26 | |||
| 27 | /********************* Driver for on-board I2C adapter *********************/ | ||
| 28 | |||
| 29 | /* #define GO7007_I2C_DEBUG */ | ||
| 30 | |||
| 31 | #define SPI_I2C_ADDR_BASE 0x1400 | ||
| 32 | #define STATUS_REG_ADDR (SPI_I2C_ADDR_BASE + 0x2) | ||
| 33 | #define I2C_CTRL_REG_ADDR (SPI_I2C_ADDR_BASE + 0x6) | ||
| 34 | #define I2C_DEV_UP_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x7) | ||
| 35 | #define I2C_LO_ADDR_REG_ADDR (SPI_I2C_ADDR_BASE + 0x8) | ||
| 36 | #define I2C_DATA_REG_ADDR (SPI_I2C_ADDR_BASE + 0x9) | ||
| 37 | #define I2C_CLKFREQ_REG_ADDR (SPI_I2C_ADDR_BASE + 0xa) | ||
| 38 | |||
| 39 | #define I2C_STATE_MASK 0x0007 | ||
| 40 | #define I2C_READ_READY_MASK 0x0008 | ||
| 41 | |||
| 42 | /* There is only one I2C port on the TW2804 that feeds all four GO7007 VIPs | ||
| 43 | * on the Adlink PCI-MPG24, so access is shared between all of them. */ | ||
| 44 | static DEFINE_MUTEX(adlink_mpg24_i2c_lock); | ||
| 45 | |||
| 46 | static int go7007_i2c_xfer(struct go7007 *go, u16 addr, int read, | ||
| 47 | u16 command, int flags, u8 *data) | ||
| 48 | { | ||
| 49 | int i, ret = -EIO; | ||
| 50 | u16 val; | ||
| 51 | |||
| 52 | if (go->status == STATUS_SHUTDOWN) | ||
| 53 | return -ENODEV; | ||
| 54 | |||
| 55 | #ifdef GO7007_I2C_DEBUG | ||
| 56 | if (read) | ||
| 57 | dev_dbg(go->dev, "go7007-i2c: reading 0x%02x on 0x%02x\n", | ||
| 58 | command, addr); | ||
| 59 | else | ||
| 60 | dev_dbg(go->dev, | ||
| 61 | "go7007-i2c: writing 0x%02x to 0x%02x on 0x%02x\n", | ||
| 62 | *data, command, addr); | ||
| 63 | #endif | ||
| 64 | |||
| 65 | mutex_lock(&go->hw_lock); | ||
| 66 | |||
| 67 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { | ||
| 68 | /* Bridge the I2C port on this GO7007 to the shared bus */ | ||
| 69 | mutex_lock(&adlink_mpg24_i2c_lock); | ||
| 70 | go7007_write_addr(go, 0x3c82, 0x0020); | ||
| 71 | } | ||
| 72 | |||
| 73 | /* Wait for I2C adapter to be ready */ | ||
| 74 | for (i = 0; i < 10; ++i) { | ||
| 75 | if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0) | ||
| 76 | goto i2c_done; | ||
| 77 | if (!(val & I2C_STATE_MASK)) | ||
| 78 | break; | ||
| 79 | msleep(100); | ||
| 80 | } | ||
| 81 | if (i == 10) { | ||
| 82 | dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n"); | ||
| 83 | goto i2c_done; | ||
| 84 | } | ||
| 85 | |||
| 86 | /* Set target register (command) */ | ||
| 87 | go7007_write_addr(go, I2C_CTRL_REG_ADDR, flags); | ||
| 88 | go7007_write_addr(go, I2C_LO_ADDR_REG_ADDR, command); | ||
| 89 | |||
| 90 | /* If we're writing, send the data and target address and we're done */ | ||
| 91 | if (!read) { | ||
| 92 | go7007_write_addr(go, I2C_DATA_REG_ADDR, *data); | ||
| 93 | go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR, | ||
| 94 | (addr << 9) | (command >> 8)); | ||
| 95 | ret = 0; | ||
| 96 | goto i2c_done; | ||
| 97 | } | ||
| 98 | |||
| 99 | /* Otherwise, we're reading. First clear i2c_rx_data_rdy. */ | ||
| 100 | if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0) | ||
| 101 | goto i2c_done; | ||
| 102 | |||
| 103 | /* Send the target address plus read flag */ | ||
| 104 | go7007_write_addr(go, I2C_DEV_UP_ADDR_REG_ADDR, | ||
| 105 | (addr << 9) | 0x0100 | (command >> 8)); | ||
| 106 | |||
| 107 | /* Wait for i2c_rx_data_rdy */ | ||
| 108 | for (i = 0; i < 10; ++i) { | ||
| 109 | if (go7007_read_addr(go, STATUS_REG_ADDR, &val) < 0) | ||
| 110 | goto i2c_done; | ||
| 111 | if (val & I2C_READ_READY_MASK) | ||
| 112 | break; | ||
| 113 | msleep(100); | ||
| 114 | } | ||
| 115 | if (i == 10) { | ||
| 116 | dev_err(go->dev, "go7007-i2c: I2C adapter is hung\n"); | ||
| 117 | goto i2c_done; | ||
| 118 | } | ||
| 119 | |||
| 120 | /* Retrieve the read byte */ | ||
| 121 | if (go7007_read_addr(go, I2C_DATA_REG_ADDR, &val) < 0) | ||
| 122 | goto i2c_done; | ||
| 123 | *data = val; | ||
| 124 | ret = 0; | ||
| 125 | |||
| 126 | i2c_done: | ||
| 127 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) { | ||
| 128 | /* Isolate the I2C port on this GO7007 from the shared bus */ | ||
| 129 | go7007_write_addr(go, 0x3c82, 0x0000); | ||
| 130 | mutex_unlock(&adlink_mpg24_i2c_lock); | ||
| 131 | } | ||
| 132 | mutex_unlock(&go->hw_lock); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int go7007_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | ||
| 137 | unsigned short flags, char read_write, | ||
| 138 | u8 command, int size, union i2c_smbus_data *data) | ||
| 139 | { | ||
| 140 | struct go7007 *go = i2c_get_adapdata(adapter); | ||
| 141 | |||
| 142 | if (size != I2C_SMBUS_BYTE_DATA) | ||
| 143 | return -EIO; | ||
| 144 | return go7007_i2c_xfer(go, addr, read_write == I2C_SMBUS_READ, command, | ||
| 145 | flags & I2C_CLIENT_SCCB ? 0x10 : 0x00, &data->byte); | ||
| 146 | } | ||
| 147 | |||
| 148 | /* VERY LIMITED I2C master xfer function -- only needed because the | ||
| 149 | * SMBus functions only support 8-bit commands and the SAA7135 uses | ||
| 150 | * 16-bit commands. The I2C interface on the GO7007, as limited as | ||
| 151 | * it is, does support this mode. */ | ||
| 152 | |||
| 153 | static int go7007_i2c_master_xfer(struct i2c_adapter *adapter, | ||
| 154 | struct i2c_msg msgs[], int num) | ||
| 155 | { | ||
| 156 | struct go7007 *go = i2c_get_adapdata(adapter); | ||
| 157 | int i; | ||
| 158 | |||
| 159 | for (i = 0; i < num; ++i) { | ||
| 160 | /* We can only do two things here -- write three bytes, or | ||
| 161 | * write two bytes and read one byte. */ | ||
| 162 | if (msgs[i].len == 2) { | ||
| 163 | if (i + 1 == num || msgs[i].addr != msgs[i + 1].addr || | ||
| 164 | (msgs[i].flags & I2C_M_RD) || | ||
| 165 | !(msgs[i + 1].flags & I2C_M_RD) || | ||
| 166 | msgs[i + 1].len != 1) | ||
| 167 | return -EIO; | ||
| 168 | if (go7007_i2c_xfer(go, msgs[i].addr, 1, | ||
| 169 | (msgs[i].buf[0] << 8) | msgs[i].buf[1], | ||
| 170 | 0x01, &msgs[i + 1].buf[0]) < 0) | ||
| 171 | return -EIO; | ||
| 172 | ++i; | ||
| 173 | } else if (msgs[i].len == 3) { | ||
| 174 | if (msgs[i].flags & I2C_M_RD) | ||
| 175 | return -EIO; | ||
| 176 | if (msgs[i].len != 3) | ||
| 177 | return -EIO; | ||
| 178 | if (go7007_i2c_xfer(go, msgs[i].addr, 0, | ||
| 179 | (msgs[i].buf[0] << 8) | msgs[i].buf[1], | ||
| 180 | 0x01, &msgs[i].buf[2]) < 0) | ||
| 181 | return -EIO; | ||
| 182 | } else | ||
| 183 | return -EIO; | ||
| 184 | } | ||
| 185 | |||
| 186 | return num; | ||
| 187 | } | ||
| 188 | |||
| 189 | static u32 go7007_functionality(struct i2c_adapter *adapter) | ||
| 190 | { | ||
| 191 | return I2C_FUNC_SMBUS_BYTE_DATA; | ||
| 192 | } | ||
| 193 | |||
| 194 | static struct i2c_algorithm go7007_algo = { | ||
| 195 | .smbus_xfer = go7007_smbus_xfer, | ||
| 196 | .master_xfer = go7007_i2c_master_xfer, | ||
| 197 | .functionality = go7007_functionality, | ||
| 198 | }; | ||
| 199 | |||
| 200 | static struct i2c_adapter go7007_adap_templ = { | ||
| 201 | .owner = THIS_MODULE, | ||
| 202 | .name = "WIS GO7007SB", | ||
| 203 | .algo = &go7007_algo, | ||
| 204 | }; | ||
| 205 | |||
| 206 | int go7007_i2c_init(struct go7007 *go) | ||
| 207 | { | ||
| 208 | memcpy(&go->i2c_adapter, &go7007_adap_templ, | ||
| 209 | sizeof(go7007_adap_templ)); | ||
| 210 | go->i2c_adapter.dev.parent = go->dev; | ||
| 211 | i2c_set_adapdata(&go->i2c_adapter, go); | ||
| 212 | if (i2c_add_adapter(&go->i2c_adapter) < 0) { | ||
| 213 | dev_err(go->dev, | ||
| 214 | "go7007-i2c: error: i2c_add_adapter failed\n"); | ||
| 215 | return -1; | ||
| 216 | } | ||
| 217 | return 0; | ||
| 218 | } | ||
diff --git a/drivers/media/usb/go7007/go7007-loader.c b/drivers/media/usb/go7007/go7007-loader.c new file mode 100644 index 000000000000..042f78a31283 --- /dev/null +++ b/drivers/media/usb/go7007/go7007-loader.c | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008 Sensoray Company Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/usb.h> | ||
| 17 | #include <linux/firmware.h> | ||
| 18 | #include <cypress_firmware.h> | ||
| 19 | |||
| 20 | struct fw_config { | ||
| 21 | u16 vendor; | ||
| 22 | u16 product; | ||
| 23 | const char * const fw_name1; | ||
| 24 | const char * const fw_name2; | ||
| 25 | }; | ||
| 26 | |||
| 27 | static struct fw_config fw_configs[] = { | ||
| 28 | { 0x1943, 0xa250, "go7007/s2250-1.fw", "go7007/s2250-2.fw" }, | ||
| 29 | { 0x093b, 0xa002, "go7007/px-m402u.fw", NULL }, | ||
| 30 | { 0x093b, 0xa004, "go7007/px-tv402u.fw", NULL }, | ||
| 31 | { 0x0eb1, 0x6666, "go7007/lr192.fw", NULL }, | ||
| 32 | { 0x0eb1, 0x6668, "go7007/wis-startrek.fw", NULL }, | ||
| 33 | { 0, 0, NULL, NULL } | ||
| 34 | }; | ||
| 35 | MODULE_FIRMWARE("go7007/s2250-1.fw"); | ||
| 36 | MODULE_FIRMWARE("go7007/s2250-2.fw"); | ||
| 37 | MODULE_FIRMWARE("go7007/px-m402u.fw"); | ||
| 38 | MODULE_FIRMWARE("go7007/px-tv402u.fw"); | ||
| 39 | MODULE_FIRMWARE("go7007/lr192.fw"); | ||
| 40 | MODULE_FIRMWARE("go7007/wis-startrek.fw"); | ||
| 41 | |||
| 42 | static int go7007_loader_probe(struct usb_interface *interface, | ||
| 43 | const struct usb_device_id *id) | ||
| 44 | { | ||
| 45 | struct usb_device *usbdev; | ||
| 46 | const struct firmware *fw; | ||
| 47 | u16 vendor, product; | ||
| 48 | const char *fw1, *fw2; | ||
| 49 | int ret; | ||
| 50 | int i; | ||
| 51 | |||
| 52 | usbdev = usb_get_dev(interface_to_usbdev(interface)); | ||
| 53 | if (!usbdev) | ||
| 54 | goto failed2; | ||
| 55 | |||
| 56 | if (usbdev->descriptor.bNumConfigurations != 1) { | ||
| 57 | dev_err(&interface->dev, "can't handle multiple config\n"); | ||
| 58 | goto failed2; | ||
| 59 | } | ||
| 60 | |||
| 61 | vendor = le16_to_cpu(usbdev->descriptor.idVendor); | ||
| 62 | product = le16_to_cpu(usbdev->descriptor.idProduct); | ||
| 63 | |||
| 64 | for (i = 0; fw_configs[i].fw_name1; i++) | ||
| 65 | if (fw_configs[i].vendor == vendor && | ||
| 66 | fw_configs[i].product == product) | ||
| 67 | break; | ||
| 68 | |||
| 69 | /* Should never happen */ | ||
| 70 | if (fw_configs[i].fw_name1 == NULL) | ||
| 71 | goto failed2; | ||
| 72 | |||
| 73 | fw1 = fw_configs[i].fw_name1; | ||
| 74 | fw2 = fw_configs[i].fw_name2; | ||
| 75 | |||
| 76 | dev_info(&interface->dev, "loading firmware %s\n", fw1); | ||
| 77 | |||
| 78 | if (request_firmware(&fw, fw1, &usbdev->dev)) { | ||
| 79 | dev_err(&interface->dev, | ||
| 80 | "unable to load firmware from file \"%s\"\n", fw1); | ||
| 81 | goto failed2; | ||
| 82 | } | ||
| 83 | ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2); | ||
| 84 | release_firmware(fw); | ||
| 85 | if (0 != ret) { | ||
| 86 | dev_err(&interface->dev, "loader download failed\n"); | ||
| 87 | goto failed2; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (fw2 == NULL) | ||
| 91 | return 0; | ||
| 92 | |||
| 93 | if (request_firmware(&fw, fw2, &usbdev->dev)) { | ||
| 94 | dev_err(&interface->dev, | ||
| 95 | "unable to load firmware from file \"%s\"\n", fw2); | ||
| 96 | goto failed2; | ||
| 97 | } | ||
| 98 | ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2); | ||
| 99 | release_firmware(fw); | ||
| 100 | if (0 != ret) { | ||
| 101 | dev_err(&interface->dev, "firmware download failed\n"); | ||
| 102 | goto failed2; | ||
| 103 | } | ||
| 104 | return 0; | ||
| 105 | |||
| 106 | failed2: | ||
| 107 | usb_put_dev(usbdev); | ||
| 108 | dev_err(&interface->dev, "probe failed\n"); | ||
| 109 | return -ENODEV; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void go7007_loader_disconnect(struct usb_interface *interface) | ||
| 113 | { | ||
| 114 | dev_info(&interface->dev, "disconnect\n"); | ||
| 115 | usb_put_dev(interface_to_usbdev(interface)); | ||
| 116 | usb_set_intfdata(interface, NULL); | ||
| 117 | } | ||
| 118 | |||
| 119 | static const struct usb_device_id go7007_loader_ids[] = { | ||
| 120 | { USB_DEVICE(0x1943, 0xa250) }, | ||
| 121 | { USB_DEVICE(0x093b, 0xa002) }, | ||
| 122 | { USB_DEVICE(0x093b, 0xa004) }, | ||
| 123 | { USB_DEVICE(0x0eb1, 0x6666) }, | ||
| 124 | { USB_DEVICE(0x0eb1, 0x6668) }, | ||
| 125 | {} /* Terminating entry */ | ||
| 126 | }; | ||
| 127 | |||
| 128 | MODULE_DEVICE_TABLE(usb, go7007_loader_ids); | ||
| 129 | |||
| 130 | static struct usb_driver go7007_loader_driver = { | ||
| 131 | .name = "go7007-loader", | ||
| 132 | .probe = go7007_loader_probe, | ||
| 133 | .disconnect = go7007_loader_disconnect, | ||
| 134 | .id_table = go7007_loader_ids, | ||
| 135 | }; | ||
| 136 | |||
| 137 | module_usb_driver(go7007_loader_driver); | ||
| 138 | |||
| 139 | MODULE_AUTHOR(""); | ||
| 140 | MODULE_DESCRIPTION("firmware loader for go7007-usb"); | ||
| 141 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h new file mode 100644 index 000000000000..2251c3f99d1d --- /dev/null +++ b/drivers/media/usb/go7007/go7007-priv.h | |||
| @@ -0,0 +1,306 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * This is the private include file for the go7007 driver. It should not | ||
| 16 | * be included by anybody but the driver itself, and especially not by | ||
| 17 | * user-space applications. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <media/v4l2-device.h> | ||
| 21 | #include <media/v4l2-ctrls.h> | ||
| 22 | #include <media/v4l2-fh.h> | ||
| 23 | #include <media/videobuf2-core.h> | ||
| 24 | |||
| 25 | struct go7007; | ||
| 26 | |||
| 27 | /* IDs to activate board-specific support code */ | ||
| 28 | #define GO7007_BOARDID_MATRIX_II 0 | ||
| 29 | #define GO7007_BOARDID_MATRIX_RELOAD 1 | ||
| 30 | #define GO7007_BOARDID_STAR_TREK 2 | ||
| 31 | #define GO7007_BOARDID_PCI_VOYAGER 3 | ||
| 32 | #define GO7007_BOARDID_XMEN 4 | ||
| 33 | #define GO7007_BOARDID_XMEN_II 5 | ||
| 34 | #define GO7007_BOARDID_XMEN_III 6 | ||
| 35 | #define GO7007_BOARDID_MATRIX_REV 7 | ||
| 36 | #define GO7007_BOARDID_PX_M402U 8 | ||
| 37 | #define GO7007_BOARDID_PX_TV402U 9 | ||
| 38 | #define GO7007_BOARDID_LIFEVIEW_LR192 10 /* TV Walker Ultra */ | ||
| 39 | #define GO7007_BOARDID_ENDURA 11 | ||
| 40 | #define GO7007_BOARDID_ADLINK_MPG24 12 | ||
| 41 | #define GO7007_BOARDID_SENSORAY_2250 13 /* Sensoray 2250/2251 */ | ||
| 42 | #define GO7007_BOARDID_ADS_USBAV_709 14 | ||
| 43 | |||
| 44 | /* Various characteristics of each board */ | ||
| 45 | #define GO7007_BOARD_HAS_AUDIO (1<<0) | ||
| 46 | #define GO7007_BOARD_USE_ONBOARD_I2C (1<<1) | ||
| 47 | #define GO7007_BOARD_HAS_TUNER (1<<2) | ||
| 48 | |||
| 49 | /* Characteristics of sensor devices */ | ||
| 50 | #define GO7007_SENSOR_VALID_POLAR (1<<0) | ||
| 51 | #define GO7007_SENSOR_HREF_POLAR (1<<1) | ||
| 52 | #define GO7007_SENSOR_VREF_POLAR (1<<2) | ||
| 53 | #define GO7007_SENSOR_FIELD_ID_POLAR (1<<3) | ||
| 54 | #define GO7007_SENSOR_BIT_WIDTH (1<<4) | ||
| 55 | #define GO7007_SENSOR_VALID_ENABLE (1<<5) | ||
| 56 | #define GO7007_SENSOR_656 (1<<6) | ||
| 57 | #define GO7007_SENSOR_CONFIG_MASK 0x7f | ||
| 58 | #define GO7007_SENSOR_TV (1<<7) | ||
| 59 | #define GO7007_SENSOR_VBI (1<<8) | ||
| 60 | #define GO7007_SENSOR_SCALING (1<<9) | ||
| 61 | #define GO7007_SENSOR_SAA7115 (1<<10) | ||
| 62 | |||
| 63 | /* Characteristics of audio sensor devices */ | ||
| 64 | #define GO7007_AUDIO_I2S_MODE_1 (1) | ||
| 65 | #define GO7007_AUDIO_I2S_MODE_2 (2) | ||
| 66 | #define GO7007_AUDIO_I2S_MODE_3 (3) | ||
| 67 | #define GO7007_AUDIO_BCLK_POLAR (1<<2) | ||
| 68 | #define GO7007_AUDIO_WORD_14 (14<<4) | ||
| 69 | #define GO7007_AUDIO_WORD_16 (16<<4) | ||
| 70 | #define GO7007_AUDIO_ONE_CHANNEL (1<<11) | ||
| 71 | #define GO7007_AUDIO_I2S_MASTER (1<<16) | ||
| 72 | #define GO7007_AUDIO_OKI_MODE (1<<17) | ||
| 73 | |||
| 74 | #define GO7007_CID_CUSTOM_BASE (V4L2_CID_DETECT_CLASS_BASE + 0x1000) | ||
| 75 | #define V4L2_CID_PIXEL_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+1) | ||
| 76 | #define V4L2_CID_MOTION_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+2) | ||
| 77 | #define V4L2_CID_MB_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+3) | ||
| 78 | #define V4L2_CID_PIXEL_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+4) | ||
| 79 | #define V4L2_CID_MOTION_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+5) | ||
| 80 | #define V4L2_CID_MB_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+6) | ||
| 81 | #define V4L2_CID_PIXEL_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+7) | ||
| 82 | #define V4L2_CID_MOTION_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+8) | ||
| 83 | #define V4L2_CID_MB_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+9) | ||
| 84 | #define V4L2_CID_PIXEL_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+10) | ||
| 85 | #define V4L2_CID_MOTION_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+11) | ||
| 86 | #define V4L2_CID_MB_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+12) | ||
| 87 | |||
| 88 | struct go7007_board_info { | ||
| 89 | unsigned int flags; | ||
| 90 | int hpi_buffer_cap; | ||
| 91 | unsigned int sensor_flags; | ||
| 92 | int sensor_width; | ||
| 93 | int sensor_height; | ||
| 94 | int sensor_framerate; | ||
| 95 | int sensor_h_offset; | ||
| 96 | int sensor_v_offset; | ||
| 97 | unsigned int audio_flags; | ||
| 98 | int audio_rate; | ||
| 99 | int audio_bclk_div; | ||
| 100 | int audio_main_div; | ||
| 101 | int num_i2c_devs; | ||
| 102 | struct go_i2c { | ||
| 103 | const char *type; | ||
| 104 | unsigned int is_video:1; | ||
| 105 | unsigned int is_audio:1; | ||
| 106 | int addr; | ||
| 107 | u32 flags; | ||
| 108 | } i2c_devs[5]; | ||
| 109 | int num_inputs; | ||
| 110 | struct { | ||
| 111 | int video_input; | ||
| 112 | int audio_index; | ||
| 113 | char *name; | ||
| 114 | } inputs[4]; | ||
| 115 | int video_config; | ||
| 116 | int num_aud_inputs; | ||
| 117 | struct { | ||
| 118 | int audio_input; | ||
| 119 | char *name; | ||
| 120 | } aud_inputs[3]; | ||
| 121 | }; | ||
| 122 | |||
| 123 | struct go7007_hpi_ops { | ||
| 124 | int (*interface_reset)(struct go7007 *go); | ||
| 125 | int (*write_interrupt)(struct go7007 *go, int addr, int data); | ||
| 126 | int (*read_interrupt)(struct go7007 *go); | ||
| 127 | int (*stream_start)(struct go7007 *go); | ||
| 128 | int (*stream_stop)(struct go7007 *go); | ||
| 129 | int (*send_firmware)(struct go7007 *go, u8 *data, int len); | ||
| 130 | int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg); | ||
| 131 | void (*release)(struct go7007 *go); | ||
| 132 | }; | ||
| 133 | |||
| 134 | /* The video buffer size must be a multiple of PAGE_SIZE */ | ||
| 135 | #define GO7007_BUF_PAGES (128 * 1024 / PAGE_SIZE) | ||
| 136 | #define GO7007_BUF_SIZE (GO7007_BUF_PAGES << PAGE_SHIFT) | ||
| 137 | |||
| 138 | struct go7007_buffer { | ||
| 139 | struct vb2_buffer vb; | ||
| 140 | struct list_head list; | ||
| 141 | unsigned int frame_offset; | ||
| 142 | u32 modet_active; | ||
| 143 | }; | ||
| 144 | |||
| 145 | #define GO7007_RATIO_1_1 0 | ||
| 146 | #define GO7007_RATIO_4_3 1 | ||
| 147 | #define GO7007_RATIO_16_9 2 | ||
| 148 | |||
| 149 | enum go7007_parser_state { | ||
| 150 | STATE_DATA, | ||
| 151 | STATE_00, | ||
| 152 | STATE_00_00, | ||
| 153 | STATE_00_00_01, | ||
| 154 | STATE_FF, | ||
| 155 | STATE_VBI_LEN_A, | ||
| 156 | STATE_VBI_LEN_B, | ||
| 157 | STATE_MODET_MAP, | ||
| 158 | STATE_UNPARSED, | ||
| 159 | }; | ||
| 160 | |||
| 161 | struct go7007 { | ||
| 162 | struct device *dev; | ||
| 163 | u8 bus_info[32]; | ||
| 164 | const struct go7007_board_info *board_info; | ||
| 165 | unsigned int board_id; | ||
| 166 | int tuner_type; | ||
| 167 | int channel_number; /* for multi-channel boards like Adlink PCI-MPG24 */ | ||
| 168 | char name[64]; | ||
| 169 | struct video_device vdev; | ||
| 170 | void *boot_fw; | ||
| 171 | unsigned boot_fw_len; | ||
| 172 | struct v4l2_device v4l2_dev; | ||
| 173 | struct v4l2_ctrl_handler hdl; | ||
| 174 | struct v4l2_ctrl *mpeg_video_encoding; | ||
| 175 | struct v4l2_ctrl *mpeg_video_gop_size; | ||
| 176 | struct v4l2_ctrl *mpeg_video_gop_closure; | ||
| 177 | struct v4l2_ctrl *mpeg_video_bitrate; | ||
| 178 | struct v4l2_ctrl *mpeg_video_aspect_ratio; | ||
| 179 | struct v4l2_ctrl *mpeg_video_b_frames; | ||
| 180 | struct v4l2_ctrl *mpeg_video_rep_seqheader; | ||
| 181 | struct v4l2_ctrl *modet_mode; | ||
| 182 | enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status; | ||
| 183 | spinlock_t spinlock; | ||
| 184 | struct mutex hw_lock; | ||
| 185 | struct mutex serialize_lock; | ||
| 186 | int audio_enabled; | ||
| 187 | struct v4l2_subdev *sd_video; | ||
| 188 | struct v4l2_subdev *sd_audio; | ||
| 189 | u8 usb_buf[16]; | ||
| 190 | |||
| 191 | /* Video input */ | ||
| 192 | int input; | ||
| 193 | int aud_input; | ||
| 194 | enum { GO7007_STD_NTSC, GO7007_STD_PAL, GO7007_STD_OTHER } standard; | ||
| 195 | v4l2_std_id std; | ||
| 196 | int sensor_framerate; | ||
| 197 | int width; | ||
| 198 | int height; | ||
| 199 | int encoder_h_offset; | ||
| 200 | int encoder_v_offset; | ||
| 201 | unsigned int encoder_h_halve:1; | ||
| 202 | unsigned int encoder_v_halve:1; | ||
| 203 | unsigned int encoder_subsample:1; | ||
| 204 | |||
| 205 | /* Encoder config */ | ||
| 206 | u32 format; | ||
| 207 | int bitrate; | ||
| 208 | int fps_scale; | ||
| 209 | int pali; | ||
| 210 | int aspect_ratio; | ||
| 211 | int gop_size; | ||
| 212 | unsigned int ipb:1; | ||
| 213 | unsigned int closed_gop:1; | ||
| 214 | unsigned int repeat_seqhead:1; | ||
| 215 | unsigned int seq_header_enable:1; | ||
| 216 | unsigned int gop_header_enable:1; | ||
| 217 | unsigned int dvd_mode:1; | ||
| 218 | unsigned int interlace_coding:1; | ||
| 219 | |||
| 220 | /* Motion detection */ | ||
| 221 | unsigned int modet_enable:1; | ||
| 222 | struct { | ||
| 223 | unsigned int enable:1; | ||
| 224 | int pixel_threshold; | ||
| 225 | int motion_threshold; | ||
| 226 | int mb_threshold; | ||
| 227 | } modet[4]; | ||
| 228 | unsigned char modet_map[1624]; | ||
| 229 | unsigned char active_map[216]; | ||
| 230 | u32 modet_event_status; | ||
| 231 | |||
| 232 | /* Video streaming */ | ||
| 233 | struct mutex queue_lock; | ||
| 234 | struct vb2_queue vidq; | ||
| 235 | enum go7007_parser_state state; | ||
| 236 | int parse_length; | ||
| 237 | u16 modet_word; | ||
| 238 | int seen_frame; | ||
| 239 | u32 next_seq; | ||
| 240 | struct list_head vidq_active; | ||
| 241 | wait_queue_head_t frame_waitq; | ||
| 242 | struct go7007_buffer *active_buf; | ||
| 243 | |||
| 244 | /* Audio streaming */ | ||
| 245 | void (*audio_deliver)(struct go7007 *go, u8 *buf, int length); | ||
| 246 | void *snd_context; | ||
| 247 | |||
| 248 | /* I2C */ | ||
| 249 | int i2c_adapter_online; | ||
| 250 | struct i2c_adapter i2c_adapter; | ||
| 251 | |||
| 252 | /* HPI driver */ | ||
| 253 | struct go7007_hpi_ops *hpi_ops; | ||
| 254 | void *hpi_context; | ||
| 255 | int interrupt_available; | ||
| 256 | wait_queue_head_t interrupt_waitq; | ||
| 257 | unsigned short interrupt_value; | ||
| 258 | unsigned short interrupt_data; | ||
| 259 | }; | ||
| 260 | |||
| 261 | static inline struct go7007 *to_go7007(struct v4l2_device *v4l2_dev) | ||
| 262 | { | ||
| 263 | return container_of(v4l2_dev, struct go7007, v4l2_dev); | ||
| 264 | } | ||
| 265 | |||
| 266 | /* All of these must be called with the hpi_lock mutex held! */ | ||
| 267 | #define go7007_interface_reset(go) \ | ||
| 268 | ((go)->hpi_ops->interface_reset(go)) | ||
| 269 | #define go7007_write_interrupt(go, x, y) \ | ||
| 270 | ((go)->hpi_ops->write_interrupt)((go), (x), (y)) | ||
| 271 | #define go7007_stream_start(go) \ | ||
| 272 | ((go)->hpi_ops->stream_start(go)) | ||
| 273 | #define go7007_stream_stop(go) \ | ||
| 274 | ((go)->hpi_ops->stream_stop(go)) | ||
| 275 | #define go7007_send_firmware(go, x, y) \ | ||
| 276 | ((go)->hpi_ops->send_firmware)((go), (x), (y)) | ||
| 277 | #define go7007_write_addr(go, x, y) \ | ||
| 278 | ((go)->hpi_ops->write_interrupt)((go), (x)|0x8000, (y)) | ||
| 279 | |||
| 280 | /* go7007-driver.c */ | ||
| 281 | int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data); | ||
| 282 | int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data); | ||
| 283 | int go7007_boot_encoder(struct go7007 *go, int init_i2c); | ||
| 284 | int go7007_reset_encoder(struct go7007 *go); | ||
| 285 | int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs); | ||
| 286 | int go7007_start_encoder(struct go7007 *go); | ||
| 287 | void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length); | ||
| 288 | struct go7007 *go7007_alloc(const struct go7007_board_info *board, | ||
| 289 | struct device *dev); | ||
| 290 | void go7007_update_board(struct go7007 *go); | ||
| 291 | |||
| 292 | /* go7007-fw.c */ | ||
| 293 | int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen); | ||
| 294 | |||
| 295 | /* go7007-i2c.c */ | ||
| 296 | int go7007_i2c_init(struct go7007 *go); | ||
| 297 | int go7007_i2c_remove(struct go7007 *go); | ||
| 298 | |||
| 299 | /* go7007-v4l2.c */ | ||
| 300 | int go7007_v4l2_init(struct go7007 *go); | ||
| 301 | int go7007_v4l2_ctrl_init(struct go7007 *go); | ||
| 302 | void go7007_v4l2_remove(struct go7007 *go); | ||
| 303 | |||
| 304 | /* snd-go7007.c */ | ||
| 305 | int go7007_snd_init(struct go7007 *go); | ||
| 306 | int go7007_snd_remove(struct go7007 *go); | ||
diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c new file mode 100644 index 000000000000..ece27ece8115 --- /dev/null +++ b/drivers/media/usb/go7007/go7007-usb.c | |||
| @@ -0,0 +1,1345 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/wait.h> | ||
| 19 | #include <linux/list.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/time.h> | ||
| 22 | #include <linux/mm.h> | ||
| 23 | #include <linux/usb.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <asm/byteorder.h> | ||
| 26 | #include <media/saa7115.h> | ||
| 27 | #include <media/tuner.h> | ||
| 28 | #include <media/uda1342.h> | ||
| 29 | |||
| 30 | #include "go7007-priv.h" | ||
| 31 | |||
| 32 | static unsigned int assume_endura; | ||
| 33 | module_param(assume_endura, int, 0644); | ||
| 34 | MODULE_PARM_DESC(assume_endura, | ||
| 35 | "when probing fails, hardware is a Pelco Endura"); | ||
| 36 | |||
| 37 | /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ | ||
| 38 | |||
| 39 | #define HPI_STATUS_ADDR 0xFFF4 | ||
| 40 | #define INT_PARAM_ADDR 0xFFF6 | ||
| 41 | #define INT_INDEX_ADDR 0xFFF8 | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Pipes on EZ-USB interface: | ||
| 45 | * 0 snd - Control | ||
| 46 | * 0 rcv - Control | ||
| 47 | * 2 snd - Download firmware (control) | ||
| 48 | * 4 rcv - Read Interrupt (interrupt) | ||
| 49 | * 6 rcv - Read Video (bulk) | ||
| 50 | * 8 rcv - Read Audio (bulk) | ||
| 51 | */ | ||
| 52 | |||
| 53 | #define GO7007_USB_EZUSB (1<<0) | ||
| 54 | #define GO7007_USB_EZUSB_I2C (1<<1) | ||
| 55 | |||
| 56 | struct go7007_usb_board { | ||
| 57 | unsigned int flags; | ||
| 58 | struct go7007_board_info main_info; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct go7007_usb { | ||
| 62 | const struct go7007_usb_board *board; | ||
| 63 | struct mutex i2c_lock; | ||
| 64 | struct usb_device *usbdev; | ||
| 65 | struct urb *video_urbs[8]; | ||
| 66 | struct urb *audio_urbs[8]; | ||
| 67 | struct urb *intr_urb; | ||
| 68 | }; | ||
| 69 | |||
| 70 | /*********************** Product specification data ***********************/ | ||
| 71 | |||
| 72 | static const struct go7007_usb_board board_matrix_ii = { | ||
| 73 | .flags = GO7007_USB_EZUSB, | ||
| 74 | .main_info = { | ||
| 75 | .flags = GO7007_BOARD_HAS_AUDIO | | ||
| 76 | GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 77 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 78 | GO7007_AUDIO_WORD_16, | ||
| 79 | .audio_rate = 48000, | ||
| 80 | .audio_bclk_div = 8, | ||
| 81 | .audio_main_div = 2, | ||
| 82 | .hpi_buffer_cap = 7, | ||
| 83 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 84 | GO7007_SENSOR_VALID_ENABLE | | ||
| 85 | GO7007_SENSOR_TV | | ||
| 86 | GO7007_SENSOR_SAA7115 | | ||
| 87 | GO7007_SENSOR_VBI | | ||
| 88 | GO7007_SENSOR_SCALING, | ||
| 89 | .num_i2c_devs = 1, | ||
| 90 | .i2c_devs = { | ||
| 91 | { | ||
| 92 | .type = "saa7115", | ||
| 93 | .addr = 0x20, | ||
| 94 | .is_video = 1, | ||
| 95 | }, | ||
| 96 | }, | ||
| 97 | .num_inputs = 2, | ||
| 98 | .inputs = { | ||
| 99 | { | ||
| 100 | .video_input = 0, | ||
| 101 | .name = "Composite", | ||
| 102 | }, | ||
| 103 | { | ||
| 104 | .video_input = 9, | ||
| 105 | .name = "S-Video", | ||
| 106 | }, | ||
| 107 | }, | ||
| 108 | .video_config = SAA7115_IDQ_IS_DEFAULT, | ||
| 109 | }, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const struct go7007_usb_board board_matrix_reload = { | ||
| 113 | .flags = GO7007_USB_EZUSB, | ||
| 114 | .main_info = { | ||
| 115 | .flags = GO7007_BOARD_HAS_AUDIO | | ||
| 116 | GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 117 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 118 | GO7007_AUDIO_I2S_MASTER | | ||
| 119 | GO7007_AUDIO_WORD_16, | ||
| 120 | .audio_rate = 48000, | ||
| 121 | .audio_bclk_div = 8, | ||
| 122 | .audio_main_div = 2, | ||
| 123 | .hpi_buffer_cap = 7, | ||
| 124 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 125 | GO7007_SENSOR_TV, | ||
| 126 | .num_i2c_devs = 1, | ||
| 127 | .i2c_devs = { | ||
| 128 | { | ||
| 129 | .type = "saa7113", | ||
| 130 | .addr = 0x25, | ||
| 131 | .is_video = 1, | ||
| 132 | }, | ||
| 133 | }, | ||
| 134 | .num_inputs = 2, | ||
| 135 | .inputs = { | ||
| 136 | { | ||
| 137 | .video_input = 0, | ||
| 138 | .name = "Composite", | ||
| 139 | }, | ||
| 140 | { | ||
| 141 | .video_input = 9, | ||
| 142 | .name = "S-Video", | ||
| 143 | }, | ||
| 144 | }, | ||
| 145 | .video_config = SAA7115_IDQ_IS_DEFAULT, | ||
| 146 | }, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static const struct go7007_usb_board board_star_trek = { | ||
| 150 | .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, | ||
| 151 | .main_info = { | ||
| 152 | .flags = GO7007_BOARD_HAS_AUDIO, /* | | ||
| 153 | GO7007_BOARD_HAS_TUNER, */ | ||
| 154 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 155 | GO7007_SENSOR_VALID_ENABLE | | ||
| 156 | GO7007_SENSOR_TV | | ||
| 157 | GO7007_SENSOR_SAA7115 | | ||
| 158 | GO7007_SENSOR_VBI | | ||
| 159 | GO7007_SENSOR_SCALING, | ||
| 160 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 161 | GO7007_AUDIO_WORD_16, | ||
| 162 | .audio_bclk_div = 8, | ||
| 163 | .audio_main_div = 2, | ||
| 164 | .hpi_buffer_cap = 7, | ||
| 165 | .num_i2c_devs = 1, | ||
| 166 | .i2c_devs = { | ||
| 167 | { | ||
| 168 | .type = "saa7115", | ||
| 169 | .addr = 0x20, | ||
| 170 | .is_video = 1, | ||
| 171 | }, | ||
| 172 | }, | ||
| 173 | .num_inputs = 2, | ||
| 174 | .inputs = { | ||
| 175 | /* { | ||
| 176 | * .video_input = 3, | ||
| 177 | * .audio_index = AUDIO_TUNER, | ||
| 178 | * .name = "Tuner", | ||
| 179 | * }, | ||
| 180 | */ | ||
| 181 | { | ||
| 182 | .video_input = 1, | ||
| 183 | /* .audio_index = AUDIO_EXTERN, */ | ||
| 184 | .name = "Composite", | ||
| 185 | }, | ||
| 186 | { | ||
| 187 | .video_input = 8, | ||
| 188 | /* .audio_index = AUDIO_EXTERN, */ | ||
| 189 | .name = "S-Video", | ||
| 190 | }, | ||
| 191 | }, | ||
| 192 | .video_config = SAA7115_IDQ_IS_DEFAULT, | ||
| 193 | }, | ||
| 194 | }; | ||
| 195 | |||
| 196 | static const struct go7007_usb_board board_px_tv402u = { | ||
| 197 | .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, | ||
| 198 | .main_info = { | ||
| 199 | .flags = GO7007_BOARD_HAS_AUDIO | | ||
| 200 | GO7007_BOARD_HAS_TUNER, | ||
| 201 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 202 | GO7007_SENSOR_VALID_ENABLE | | ||
| 203 | GO7007_SENSOR_TV | | ||
| 204 | GO7007_SENSOR_SAA7115 | | ||
| 205 | GO7007_SENSOR_VBI | | ||
| 206 | GO7007_SENSOR_SCALING, | ||
| 207 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 208 | GO7007_AUDIO_WORD_16, | ||
| 209 | .audio_bclk_div = 8, | ||
| 210 | .audio_main_div = 2, | ||
| 211 | .hpi_buffer_cap = 7, | ||
| 212 | .num_i2c_devs = 5, | ||
| 213 | .i2c_devs = { | ||
| 214 | { | ||
| 215 | .type = "saa7115", | ||
| 216 | .addr = 0x20, | ||
| 217 | .is_video = 1, | ||
| 218 | }, | ||
| 219 | { | ||
| 220 | .type = "uda1342", | ||
| 221 | .addr = 0x1a, | ||
| 222 | .is_audio = 1, | ||
| 223 | }, | ||
| 224 | { | ||
| 225 | .type = "tuner", | ||
| 226 | .addr = 0x60, | ||
| 227 | }, | ||
| 228 | { | ||
| 229 | .type = "tuner", | ||
| 230 | .addr = 0x43, | ||
| 231 | }, | ||
| 232 | { | ||
| 233 | .type = "sony-btf-mpx", | ||
| 234 | .addr = 0x44, | ||
| 235 | }, | ||
| 236 | }, | ||
| 237 | .num_inputs = 3, | ||
| 238 | .inputs = { | ||
| 239 | { | ||
| 240 | .video_input = 3, | ||
| 241 | .audio_index = 0, | ||
| 242 | .name = "Tuner", | ||
| 243 | }, | ||
| 244 | { | ||
| 245 | .video_input = 1, | ||
| 246 | .audio_index = 1, | ||
| 247 | .name = "Composite", | ||
| 248 | }, | ||
| 249 | { | ||
| 250 | .video_input = 8, | ||
| 251 | .audio_index = 1, | ||
| 252 | .name = "S-Video", | ||
| 253 | }, | ||
| 254 | }, | ||
| 255 | .video_config = SAA7115_IDQ_IS_DEFAULT, | ||
| 256 | .num_aud_inputs = 2, | ||
| 257 | .aud_inputs = { | ||
| 258 | { | ||
| 259 | .audio_input = UDA1342_IN2, | ||
| 260 | .name = "Tuner", | ||
| 261 | }, | ||
| 262 | { | ||
| 263 | .audio_input = UDA1342_IN1, | ||
| 264 | .name = "Line In", | ||
| 265 | }, | ||
| 266 | }, | ||
| 267 | }, | ||
| 268 | }; | ||
| 269 | |||
| 270 | static const struct go7007_usb_board board_xmen = { | ||
| 271 | .flags = 0, | ||
| 272 | .main_info = { | ||
| 273 | .flags = GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 274 | .hpi_buffer_cap = 0, | ||
| 275 | .sensor_flags = GO7007_SENSOR_VREF_POLAR, | ||
| 276 | .sensor_width = 320, | ||
| 277 | .sensor_height = 240, | ||
| 278 | .sensor_framerate = 30030, | ||
| 279 | .audio_flags = GO7007_AUDIO_ONE_CHANNEL | | ||
| 280 | GO7007_AUDIO_I2S_MODE_3 | | ||
| 281 | GO7007_AUDIO_WORD_14 | | ||
| 282 | GO7007_AUDIO_I2S_MASTER | | ||
| 283 | GO7007_AUDIO_BCLK_POLAR | | ||
| 284 | GO7007_AUDIO_OKI_MODE, | ||
| 285 | .audio_rate = 8000, | ||
| 286 | .audio_bclk_div = 48, | ||
| 287 | .audio_main_div = 1, | ||
| 288 | .num_i2c_devs = 1, | ||
| 289 | .i2c_devs = { | ||
| 290 | { | ||
| 291 | .type = "ov7640", | ||
| 292 | .addr = 0x21, | ||
| 293 | }, | ||
| 294 | }, | ||
| 295 | .num_inputs = 1, | ||
| 296 | .inputs = { | ||
| 297 | { | ||
| 298 | .name = "Camera", | ||
| 299 | }, | ||
| 300 | }, | ||
| 301 | }, | ||
| 302 | }; | ||
| 303 | |||
| 304 | static const struct go7007_usb_board board_matrix_revolution = { | ||
| 305 | .flags = GO7007_USB_EZUSB, | ||
| 306 | .main_info = { | ||
| 307 | .flags = GO7007_BOARD_HAS_AUDIO | | ||
| 308 | GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 309 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 310 | GO7007_AUDIO_I2S_MASTER | | ||
| 311 | GO7007_AUDIO_WORD_16, | ||
| 312 | .audio_rate = 48000, | ||
| 313 | .audio_bclk_div = 8, | ||
| 314 | .audio_main_div = 2, | ||
| 315 | .hpi_buffer_cap = 7, | ||
| 316 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 317 | GO7007_SENSOR_TV | | ||
| 318 | GO7007_SENSOR_VBI, | ||
| 319 | .num_i2c_devs = 1, | ||
| 320 | .i2c_devs = { | ||
| 321 | { | ||
| 322 | .type = "tw9903", | ||
| 323 | .is_video = 1, | ||
| 324 | .addr = 0x44, | ||
| 325 | }, | ||
| 326 | }, | ||
| 327 | .num_inputs = 2, | ||
| 328 | .inputs = { | ||
| 329 | { | ||
| 330 | .video_input = 2, | ||
| 331 | .name = "Composite", | ||
| 332 | }, | ||
| 333 | { | ||
| 334 | .video_input = 8, | ||
| 335 | .name = "S-Video", | ||
| 336 | }, | ||
| 337 | }, | ||
| 338 | }, | ||
| 339 | }; | ||
| 340 | |||
| 341 | static const struct go7007_usb_board board_lifeview_lr192 = { | ||
| 342 | .flags = GO7007_USB_EZUSB, | ||
| 343 | .main_info = { | ||
| 344 | .flags = GO7007_BOARD_HAS_AUDIO | | ||
| 345 | GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 346 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 347 | GO7007_AUDIO_WORD_16, | ||
| 348 | .audio_rate = 48000, | ||
| 349 | .audio_bclk_div = 8, | ||
| 350 | .audio_main_div = 2, | ||
| 351 | .hpi_buffer_cap = 7, | ||
| 352 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 353 | GO7007_SENSOR_VALID_ENABLE | | ||
| 354 | GO7007_SENSOR_TV | | ||
| 355 | GO7007_SENSOR_VBI | | ||
| 356 | GO7007_SENSOR_SCALING, | ||
| 357 | .num_i2c_devs = 0, | ||
| 358 | .num_inputs = 1, | ||
| 359 | .inputs = { | ||
| 360 | { | ||
| 361 | .video_input = 0, | ||
| 362 | .name = "Composite", | ||
| 363 | }, | ||
| 364 | }, | ||
| 365 | }, | ||
| 366 | }; | ||
| 367 | |||
| 368 | static const struct go7007_usb_board board_endura = { | ||
| 369 | .flags = 0, | ||
| 370 | .main_info = { | ||
| 371 | .flags = 0, | ||
| 372 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 373 | GO7007_AUDIO_I2S_MASTER | | ||
| 374 | GO7007_AUDIO_WORD_16, | ||
| 375 | .audio_rate = 8000, | ||
| 376 | .audio_bclk_div = 48, | ||
| 377 | .audio_main_div = 8, | ||
| 378 | .hpi_buffer_cap = 0, | ||
| 379 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 380 | GO7007_SENSOR_TV, | ||
| 381 | .sensor_h_offset = 8, | ||
| 382 | .num_i2c_devs = 0, | ||
| 383 | .num_inputs = 1, | ||
| 384 | .inputs = { | ||
| 385 | { | ||
| 386 | .name = "Camera", | ||
| 387 | }, | ||
| 388 | }, | ||
| 389 | }, | ||
| 390 | }; | ||
| 391 | |||
| 392 | static const struct go7007_usb_board board_adlink_mpg24 = { | ||
| 393 | .flags = 0, | ||
| 394 | .main_info = { | ||
| 395 | .flags = GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 396 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 397 | GO7007_AUDIO_I2S_MASTER | | ||
| 398 | GO7007_AUDIO_WORD_16, | ||
| 399 | .audio_rate = 48000, | ||
| 400 | .audio_bclk_div = 8, | ||
| 401 | .audio_main_div = 2, | ||
| 402 | .hpi_buffer_cap = 0, | ||
| 403 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 404 | GO7007_SENSOR_TV | | ||
| 405 | GO7007_SENSOR_VBI, | ||
| 406 | .num_i2c_devs = 1, | ||
| 407 | .i2c_devs = { | ||
| 408 | { | ||
| 409 | .type = "tw2804", | ||
| 410 | .addr = 0x00, /* yes, really */ | ||
| 411 | .flags = I2C_CLIENT_TEN, | ||
| 412 | .is_video = 1, | ||
| 413 | }, | ||
| 414 | }, | ||
| 415 | .num_inputs = 1, | ||
| 416 | .inputs = { | ||
| 417 | { | ||
| 418 | .name = "Composite", | ||
| 419 | }, | ||
| 420 | }, | ||
| 421 | }, | ||
| 422 | }; | ||
| 423 | |||
| 424 | static const struct go7007_usb_board board_sensoray_2250 = { | ||
| 425 | .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, | ||
| 426 | .main_info = { | ||
| 427 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 428 | GO7007_AUDIO_I2S_MASTER | | ||
| 429 | GO7007_AUDIO_WORD_16, | ||
| 430 | .flags = GO7007_BOARD_HAS_AUDIO, | ||
| 431 | .audio_rate = 48000, | ||
| 432 | .audio_bclk_div = 8, | ||
| 433 | .audio_main_div = 2, | ||
| 434 | .hpi_buffer_cap = 7, | ||
| 435 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 436 | GO7007_SENSOR_TV, | ||
| 437 | .num_i2c_devs = 1, | ||
| 438 | .i2c_devs = { | ||
| 439 | { | ||
| 440 | .type = "s2250", | ||
| 441 | .addr = 0x43, | ||
| 442 | .is_video = 1, | ||
| 443 | .is_audio = 1, | ||
| 444 | }, | ||
| 445 | }, | ||
| 446 | .num_inputs = 2, | ||
| 447 | .inputs = { | ||
| 448 | { | ||
| 449 | .video_input = 0, | ||
| 450 | .name = "Composite", | ||
| 451 | }, | ||
| 452 | { | ||
| 453 | .video_input = 1, | ||
| 454 | .name = "S-Video", | ||
| 455 | }, | ||
| 456 | }, | ||
| 457 | .num_aud_inputs = 3, | ||
| 458 | .aud_inputs = { | ||
| 459 | { | ||
| 460 | .audio_input = 0, | ||
| 461 | .name = "Line In", | ||
| 462 | }, | ||
| 463 | { | ||
| 464 | .audio_input = 1, | ||
| 465 | .name = "Mic", | ||
| 466 | }, | ||
| 467 | { | ||
| 468 | .audio_input = 2, | ||
| 469 | .name = "Mic Boost", | ||
| 470 | }, | ||
| 471 | }, | ||
| 472 | }, | ||
| 473 | }; | ||
| 474 | |||
| 475 | static const struct go7007_usb_board board_ads_usbav_709 = { | ||
| 476 | .flags = GO7007_USB_EZUSB, | ||
| 477 | .main_info = { | ||
| 478 | .flags = GO7007_BOARD_HAS_AUDIO | | ||
| 479 | GO7007_BOARD_USE_ONBOARD_I2C, | ||
| 480 | .audio_flags = GO7007_AUDIO_I2S_MODE_1 | | ||
| 481 | GO7007_AUDIO_I2S_MASTER | | ||
| 482 | GO7007_AUDIO_WORD_16, | ||
| 483 | .audio_rate = 48000, | ||
| 484 | .audio_bclk_div = 8, | ||
| 485 | .audio_main_div = 2, | ||
| 486 | .hpi_buffer_cap = 7, | ||
| 487 | .sensor_flags = GO7007_SENSOR_656 | | ||
| 488 | GO7007_SENSOR_TV | | ||
| 489 | GO7007_SENSOR_VBI, | ||
| 490 | .num_i2c_devs = 1, | ||
| 491 | .i2c_devs = { | ||
| 492 | { | ||
| 493 | .type = "tw9906", | ||
| 494 | .is_video = 1, | ||
| 495 | .addr = 0x44, | ||
| 496 | }, | ||
| 497 | }, | ||
| 498 | .num_inputs = 2, | ||
| 499 | .inputs = { | ||
| 500 | { | ||
| 501 | .video_input = 0, | ||
| 502 | .name = "Composite", | ||
| 503 | }, | ||
| 504 | { | ||
| 505 | .video_input = 10, | ||
| 506 | .name = "S-Video", | ||
| 507 | }, | ||
| 508 | }, | ||
| 509 | }, | ||
| 510 | }; | ||
| 511 | |||
| 512 | static const struct usb_device_id go7007_usb_id_table[] = { | ||
| 513 | { | ||
| 514 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | | ||
| 515 | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 516 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 517 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 518 | .bcdDevice_lo = 0x200, /* Revision number of XMen */ | ||
| 519 | .bcdDevice_hi = 0x200, | ||
| 520 | .bInterfaceClass = 255, | ||
| 521 | .bInterfaceSubClass = 0, | ||
| 522 | .bInterfaceProtocol = 255, | ||
| 523 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN, | ||
| 524 | }, | ||
| 525 | { | ||
| 526 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 527 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 528 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 529 | .bcdDevice_lo = 0x202, /* Revision number of Matrix II */ | ||
| 530 | .bcdDevice_hi = 0x202, | ||
| 531 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II, | ||
| 532 | }, | ||
| 533 | { | ||
| 534 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 535 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 536 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 537 | .bcdDevice_lo = 0x204, /* Revision number of Matrix */ | ||
| 538 | .bcdDevice_hi = 0x204, /* Reloaded */ | ||
| 539 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD, | ||
| 540 | }, | ||
| 541 | { | ||
| 542 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | | ||
| 543 | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 544 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 545 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 546 | .bcdDevice_lo = 0x205, /* Revision number of XMen-II */ | ||
| 547 | .bcdDevice_hi = 0x205, | ||
| 548 | .bInterfaceClass = 255, | ||
| 549 | .bInterfaceSubClass = 0, | ||
| 550 | .bInterfaceProtocol = 255, | ||
| 551 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II, | ||
| 552 | }, | ||
| 553 | { | ||
| 554 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 555 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 556 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 557 | .bcdDevice_lo = 0x208, /* Revision number of Star Trek */ | ||
| 558 | .bcdDevice_hi = 0x208, | ||
| 559 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK, | ||
| 560 | }, | ||
| 561 | { | ||
| 562 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | | ||
| 563 | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 564 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 565 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 566 | .bcdDevice_lo = 0x209, /* Revision number of XMen-III */ | ||
| 567 | .bcdDevice_hi = 0x209, | ||
| 568 | .bInterfaceClass = 255, | ||
| 569 | .bInterfaceSubClass = 0, | ||
| 570 | .bInterfaceProtocol = 255, | ||
| 571 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III, | ||
| 572 | }, | ||
| 573 | { | ||
| 574 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 575 | .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ | ||
| 576 | .idProduct = 0x7007, /* Product ID of GO7007SB chip */ | ||
| 577 | .bcdDevice_lo = 0x210, /* Revision number of Matrix */ | ||
| 578 | .bcdDevice_hi = 0x210, /* Revolution */ | ||
| 579 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV, | ||
| 580 | }, | ||
| 581 | { | ||
| 582 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 583 | .idVendor = 0x093b, /* Vendor ID of Plextor */ | ||
| 584 | .idProduct = 0xa102, /* Product ID of M402U */ | ||
| 585 | .bcdDevice_lo = 0x1, /* revision number of Blueberry */ | ||
| 586 | .bcdDevice_hi = 0x1, | ||
| 587 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U, | ||
| 588 | }, | ||
| 589 | { | ||
| 590 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 591 | .idVendor = 0x093b, /* Vendor ID of Plextor */ | ||
| 592 | .idProduct = 0xa104, /* Product ID of TV402U */ | ||
| 593 | .bcdDevice_lo = 0x1, | ||
| 594 | .bcdDevice_hi = 0x1, | ||
| 595 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U, | ||
| 596 | }, | ||
| 597 | { | ||
| 598 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 599 | .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */ | ||
| 600 | .idProduct = 0xde00, /* Product ID of Lifeview LR192 */ | ||
| 601 | .bcdDevice_lo = 0x1, | ||
| 602 | .bcdDevice_hi = 0x1, | ||
| 603 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, | ||
| 604 | }, | ||
| 605 | { | ||
| 606 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 607 | .idVendor = 0x1943, /* Vendor ID Sensoray */ | ||
| 608 | .idProduct = 0x2250, /* Product ID of 2250/2251 */ | ||
| 609 | .bcdDevice_lo = 0x1, | ||
| 610 | .bcdDevice_hi = 0x1, | ||
| 611 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250, | ||
| 612 | }, | ||
| 613 | { | ||
| 614 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, | ||
| 615 | .idVendor = 0x06e1, /* Vendor ID of ADS Technologies */ | ||
| 616 | .idProduct = 0x0709, /* Product ID of DVD Xpress DX2 */ | ||
| 617 | .bcdDevice_lo = 0x204, | ||
| 618 | .bcdDevice_hi = 0x204, | ||
| 619 | .driver_info = (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709, | ||
| 620 | }, | ||
| 621 | { } /* Terminating entry */ | ||
| 622 | }; | ||
| 623 | |||
| 624 | MODULE_DEVICE_TABLE(usb, go7007_usb_id_table); | ||
| 625 | |||
| 626 | /********************* Driver for EZ-USB HPI interface *********************/ | ||
| 627 | |||
| 628 | static int go7007_usb_vendor_request(struct go7007 *go, int request, | ||
| 629 | int value, int index, void *transfer_buffer, int length, int in) | ||
| 630 | { | ||
| 631 | struct go7007_usb *usb = go->hpi_context; | ||
| 632 | int timeout = 5000; | ||
| 633 | |||
| 634 | if (in) { | ||
| 635 | return usb_control_msg(usb->usbdev, | ||
| 636 | usb_rcvctrlpipe(usb->usbdev, 0), request, | ||
| 637 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 638 | value, index, transfer_buffer, length, timeout); | ||
| 639 | } else { | ||
| 640 | return usb_control_msg(usb->usbdev, | ||
| 641 | usb_sndctrlpipe(usb->usbdev, 0), request, | ||
| 642 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 643 | value, index, transfer_buffer, length, timeout); | ||
| 644 | } | ||
| 645 | } | ||
| 646 | |||
| 647 | static int go7007_usb_interface_reset(struct go7007 *go) | ||
| 648 | { | ||
| 649 | struct go7007_usb *usb = go->hpi_context; | ||
| 650 | u16 intr_val, intr_data; | ||
| 651 | |||
| 652 | if (go->status == STATUS_SHUTDOWN) | ||
| 653 | return -1; | ||
| 654 | /* Reset encoder */ | ||
| 655 | if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) | ||
| 656 | return -1; | ||
| 657 | msleep(100); | ||
| 658 | |||
| 659 | if (usb->board->flags & GO7007_USB_EZUSB) { | ||
| 660 | /* Reset buffer in EZ-USB */ | ||
| 661 | pr_debug("resetting EZ-USB buffers\n"); | ||
| 662 | if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || | ||
| 663 | go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) | ||
| 664 | return -1; | ||
| 665 | |||
| 666 | /* Reset encoder again */ | ||
| 667 | if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) | ||
| 668 | return -1; | ||
| 669 | msleep(100); | ||
| 670 | } | ||
| 671 | |||
| 672 | /* Wait for an interrupt to indicate successful hardware reset */ | ||
| 673 | if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || | ||
| 674 | (intr_val & ~0x1) != 0x55aa) { | ||
| 675 | dev_err(go->dev, "unable to reset the USB interface\n"); | ||
| 676 | return -1; | ||
| 677 | } | ||
| 678 | return 0; | ||
| 679 | } | ||
| 680 | |||
| 681 | static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, | ||
| 682 | int addr, int data) | ||
| 683 | { | ||
| 684 | struct go7007_usb *usb = go->hpi_context; | ||
| 685 | int i, r; | ||
| 686 | u16 status_reg = 0; | ||
| 687 | int timeout = 500; | ||
| 688 | |||
| 689 | pr_debug("WriteInterrupt: %04x %04x\n", addr, data); | ||
| 690 | |||
| 691 | for (i = 0; i < 100; ++i) { | ||
| 692 | r = usb_control_msg(usb->usbdev, | ||
| 693 | usb_rcvctrlpipe(usb->usbdev, 0), 0x14, | ||
| 694 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 695 | 0, HPI_STATUS_ADDR, go->usb_buf, | ||
| 696 | sizeof(status_reg), timeout); | ||
| 697 | if (r < 0) | ||
| 698 | break; | ||
| 699 | status_reg = le16_to_cpu(*((u16 *)go->usb_buf)); | ||
| 700 | if (!(status_reg & 0x0010)) | ||
| 701 | break; | ||
| 702 | msleep(10); | ||
| 703 | } | ||
| 704 | if (r < 0) | ||
| 705 | goto write_int_error; | ||
| 706 | if (i == 100) { | ||
| 707 | dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg); | ||
| 708 | return -1; | ||
| 709 | } | ||
| 710 | r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, | ||
| 711 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, data, | ||
| 712 | INT_PARAM_ADDR, NULL, 0, timeout); | ||
| 713 | if (r < 0) | ||
| 714 | goto write_int_error; | ||
| 715 | r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), | ||
| 716 | 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr, | ||
| 717 | INT_INDEX_ADDR, NULL, 0, timeout); | ||
| 718 | if (r < 0) | ||
| 719 | goto write_int_error; | ||
| 720 | return 0; | ||
| 721 | |||
| 722 | write_int_error: | ||
| 723 | dev_err(go->dev, "error in WriteInterrupt: %d\n", r); | ||
| 724 | return r; | ||
| 725 | } | ||
| 726 | |||
| 727 | static int go7007_usb_onboard_write_interrupt(struct go7007 *go, | ||
| 728 | int addr, int data) | ||
| 729 | { | ||
| 730 | struct go7007_usb *usb = go->hpi_context; | ||
| 731 | int r; | ||
| 732 | int timeout = 500; | ||
| 733 | |||
| 734 | pr_debug("WriteInterrupt: %04x %04x\n", addr, data); | ||
| 735 | |||
| 736 | go->usb_buf[0] = data & 0xff; | ||
| 737 | go->usb_buf[1] = data >> 8; | ||
| 738 | go->usb_buf[2] = addr & 0xff; | ||
| 739 | go->usb_buf[3] = addr >> 8; | ||
| 740 | go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0; | ||
| 741 | r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00, | ||
| 742 | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, | ||
| 743 | 0xf0f0, go->usb_buf, 8, timeout); | ||
| 744 | if (r < 0) { | ||
| 745 | dev_err(go->dev, "error in WriteInterrupt: %d\n", r); | ||
| 746 | return r; | ||
| 747 | } | ||
| 748 | return 0; | ||
| 749 | } | ||
| 750 | |||
| 751 | static void go7007_usb_readinterrupt_complete(struct urb *urb) | ||
| 752 | { | ||
| 753 | struct go7007 *go = (struct go7007 *)urb->context; | ||
| 754 | u16 *regs = (u16 *)urb->transfer_buffer; | ||
| 755 | int status = urb->status; | ||
| 756 | |||
| 757 | if (status) { | ||
| 758 | if (status != -ESHUTDOWN && | ||
| 759 | go->status != STATUS_SHUTDOWN) { | ||
| 760 | dev_err(go->dev, "error in read interrupt: %d\n", urb->status); | ||
| 761 | } else { | ||
| 762 | wake_up(&go->interrupt_waitq); | ||
| 763 | return; | ||
| 764 | } | ||
| 765 | } else if (urb->actual_length != urb->transfer_buffer_length) { | ||
| 766 | dev_err(go->dev, "short read in interrupt pipe!\n"); | ||
| 767 | } else { | ||
| 768 | go->interrupt_available = 1; | ||
| 769 | go->interrupt_data = __le16_to_cpu(regs[0]); | ||
| 770 | go->interrupt_value = __le16_to_cpu(regs[1]); | ||
| 771 | pr_debug("ReadInterrupt: %04x %04x\n", | ||
| 772 | go->interrupt_value, go->interrupt_data); | ||
| 773 | } | ||
| 774 | |||
| 775 | wake_up(&go->interrupt_waitq); | ||
| 776 | } | ||
| 777 | |||
| 778 | static int go7007_usb_read_interrupt(struct go7007 *go) | ||
| 779 | { | ||
| 780 | struct go7007_usb *usb = go->hpi_context; | ||
| 781 | int r; | ||
| 782 | |||
| 783 | r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); | ||
| 784 | if (r < 0) { | ||
| 785 | dev_err(go->dev, "unable to submit interrupt urb: %d\n", r); | ||
| 786 | return r; | ||
| 787 | } | ||
| 788 | return 0; | ||
| 789 | } | ||
| 790 | |||
| 791 | static void go7007_usb_read_video_pipe_complete(struct urb *urb) | ||
| 792 | { | ||
| 793 | struct go7007 *go = (struct go7007 *)urb->context; | ||
| 794 | int r, status = urb->status; | ||
| 795 | |||
| 796 | if (!vb2_is_streaming(&go->vidq)) { | ||
| 797 | wake_up_interruptible(&go->frame_waitq); | ||
| 798 | return; | ||
| 799 | } | ||
| 800 | if (status) { | ||
| 801 | dev_err(go->dev, "error in video pipe: %d\n", status); | ||
| 802 | return; | ||
| 803 | } | ||
| 804 | if (urb->actual_length != urb->transfer_buffer_length) { | ||
| 805 | dev_err(go->dev, "short read in video pipe!\n"); | ||
| 806 | return; | ||
| 807 | } | ||
| 808 | go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); | ||
| 809 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 810 | if (r < 0) | ||
| 811 | dev_err(go->dev, "error in video pipe: %d\n", r); | ||
| 812 | } | ||
| 813 | |||
| 814 | static void go7007_usb_read_audio_pipe_complete(struct urb *urb) | ||
| 815 | { | ||
| 816 | struct go7007 *go = (struct go7007 *)urb->context; | ||
| 817 | int r, status = urb->status; | ||
| 818 | |||
| 819 | if (!vb2_is_streaming(&go->vidq)) | ||
| 820 | return; | ||
| 821 | if (status) { | ||
| 822 | dev_err(go->dev, "error in audio pipe: %d\n", | ||
| 823 | status); | ||
| 824 | return; | ||
| 825 | } | ||
| 826 | if (urb->actual_length != urb->transfer_buffer_length) { | ||
| 827 | dev_err(go->dev, "short read in audio pipe!\n"); | ||
| 828 | return; | ||
| 829 | } | ||
| 830 | if (go->audio_deliver != NULL) | ||
| 831 | go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); | ||
| 832 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 833 | if (r < 0) | ||
| 834 | dev_err(go->dev, "error in audio pipe: %d\n", r); | ||
| 835 | } | ||
| 836 | |||
| 837 | static int go7007_usb_stream_start(struct go7007 *go) | ||
| 838 | { | ||
| 839 | struct go7007_usb *usb = go->hpi_context; | ||
| 840 | int i, r; | ||
| 841 | |||
| 842 | for (i = 0; i < 8; ++i) { | ||
| 843 | r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); | ||
| 844 | if (r < 0) { | ||
| 845 | dev_err(go->dev, "error submitting video urb %d: %d\n", i, r); | ||
| 846 | goto video_submit_failed; | ||
| 847 | } | ||
| 848 | } | ||
| 849 | if (!go->audio_enabled) | ||
| 850 | return 0; | ||
| 851 | |||
| 852 | for (i = 0; i < 8; ++i) { | ||
| 853 | r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); | ||
| 854 | if (r < 0) { | ||
| 855 | dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r); | ||
| 856 | goto audio_submit_failed; | ||
| 857 | } | ||
| 858 | } | ||
| 859 | return 0; | ||
| 860 | |||
| 861 | audio_submit_failed: | ||
| 862 | for (i = 0; i < 7; ++i) | ||
| 863 | usb_kill_urb(usb->audio_urbs[i]); | ||
| 864 | video_submit_failed: | ||
| 865 | for (i = 0; i < 8; ++i) | ||
| 866 | usb_kill_urb(usb->video_urbs[i]); | ||
| 867 | return -1; | ||
| 868 | } | ||
| 869 | |||
| 870 | static int go7007_usb_stream_stop(struct go7007 *go) | ||
| 871 | { | ||
| 872 | struct go7007_usb *usb = go->hpi_context; | ||
| 873 | int i; | ||
| 874 | |||
| 875 | if (go->status == STATUS_SHUTDOWN) | ||
| 876 | return 0; | ||
| 877 | for (i = 0; i < 8; ++i) | ||
| 878 | usb_kill_urb(usb->video_urbs[i]); | ||
| 879 | if (go->audio_enabled) | ||
| 880 | for (i = 0; i < 8; ++i) | ||
| 881 | usb_kill_urb(usb->audio_urbs[i]); | ||
| 882 | return 0; | ||
| 883 | } | ||
| 884 | |||
| 885 | static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) | ||
| 886 | { | ||
| 887 | struct go7007_usb *usb = go->hpi_context; | ||
| 888 | int transferred, pipe; | ||
| 889 | int timeout = 500; | ||
| 890 | |||
| 891 | pr_debug("DownloadBuffer sending %d bytes\n", len); | ||
| 892 | |||
| 893 | if (usb->board->flags & GO7007_USB_EZUSB) | ||
| 894 | pipe = usb_sndbulkpipe(usb->usbdev, 2); | ||
| 895 | else | ||
| 896 | pipe = usb_sndbulkpipe(usb->usbdev, 3); | ||
| 897 | |||
| 898 | return usb_bulk_msg(usb->usbdev, pipe, data, len, | ||
| 899 | &transferred, timeout); | ||
| 900 | } | ||
| 901 | |||
| 902 | static void go7007_usb_release(struct go7007 *go) | ||
| 903 | { | ||
| 904 | struct go7007_usb *usb = go->hpi_context; | ||
| 905 | struct urb *vurb, *aurb; | ||
| 906 | int i; | ||
| 907 | |||
| 908 | if (usb->intr_urb) { | ||
| 909 | usb_kill_urb(usb->intr_urb); | ||
| 910 | kfree(usb->intr_urb->transfer_buffer); | ||
| 911 | usb_free_urb(usb->intr_urb); | ||
| 912 | } | ||
| 913 | |||
| 914 | /* Free USB-related structs */ | ||
| 915 | for (i = 0; i < 8; ++i) { | ||
| 916 | vurb = usb->video_urbs[i]; | ||
| 917 | if (vurb) { | ||
| 918 | usb_kill_urb(vurb); | ||
| 919 | kfree(vurb->transfer_buffer); | ||
| 920 | usb_free_urb(vurb); | ||
| 921 | } | ||
| 922 | aurb = usb->audio_urbs[i]; | ||
| 923 | if (aurb) { | ||
| 924 | usb_kill_urb(aurb); | ||
| 925 | kfree(aurb->transfer_buffer); | ||
| 926 | usb_free_urb(aurb); | ||
| 927 | } | ||
| 928 | } | ||
| 929 | |||
| 930 | kfree(go->hpi_context); | ||
| 931 | } | ||
| 932 | |||
| 933 | static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { | ||
| 934 | .interface_reset = go7007_usb_interface_reset, | ||
| 935 | .write_interrupt = go7007_usb_ezusb_write_interrupt, | ||
| 936 | .read_interrupt = go7007_usb_read_interrupt, | ||
| 937 | .stream_start = go7007_usb_stream_start, | ||
| 938 | .stream_stop = go7007_usb_stream_stop, | ||
| 939 | .send_firmware = go7007_usb_send_firmware, | ||
| 940 | .release = go7007_usb_release, | ||
| 941 | }; | ||
| 942 | |||
| 943 | static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { | ||
| 944 | .interface_reset = go7007_usb_interface_reset, | ||
| 945 | .write_interrupt = go7007_usb_onboard_write_interrupt, | ||
| 946 | .read_interrupt = go7007_usb_read_interrupt, | ||
| 947 | .stream_start = go7007_usb_stream_start, | ||
| 948 | .stream_stop = go7007_usb_stream_stop, | ||
| 949 | .send_firmware = go7007_usb_send_firmware, | ||
| 950 | .release = go7007_usb_release, | ||
| 951 | }; | ||
| 952 | |||
| 953 | /********************* Driver for EZ-USB I2C adapter *********************/ | ||
| 954 | |||
| 955 | static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, | ||
| 956 | struct i2c_msg msgs[], int num) | ||
| 957 | { | ||
| 958 | struct go7007 *go = i2c_get_adapdata(adapter); | ||
| 959 | struct go7007_usb *usb = go->hpi_context; | ||
| 960 | u8 *buf = go->usb_buf; | ||
| 961 | int buf_len, i; | ||
| 962 | int ret = -EIO; | ||
| 963 | |||
| 964 | if (go->status == STATUS_SHUTDOWN) | ||
| 965 | return -ENODEV; | ||
| 966 | |||
| 967 | mutex_lock(&usb->i2c_lock); | ||
| 968 | |||
| 969 | for (i = 0; i < num; ++i) { | ||
| 970 | /* The hardware command is "write some bytes then read some | ||
| 971 | * bytes", so we try to coalesce a write followed by a read | ||
| 972 | * into a single USB transaction */ | ||
| 973 | if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && | ||
| 974 | !(msgs[i].flags & I2C_M_RD) && | ||
| 975 | (msgs[i + 1].flags & I2C_M_RD)) { | ||
| 976 | #ifdef GO7007_I2C_DEBUG | ||
| 977 | pr_debug("i2c write/read %d/%d bytes on %02x\n", | ||
| 978 | msgs[i].len, msgs[i + 1].len, msgs[i].addr); | ||
| 979 | #endif | ||
| 980 | buf[0] = 0x01; | ||
| 981 | buf[1] = msgs[i].len + 1; | ||
| 982 | buf[2] = msgs[i].addr << 1; | ||
| 983 | memcpy(&buf[3], msgs[i].buf, msgs[i].len); | ||
| 984 | buf_len = msgs[i].len + 3; | ||
| 985 | buf[buf_len++] = msgs[++i].len; | ||
| 986 | } else if (msgs[i].flags & I2C_M_RD) { | ||
| 987 | #ifdef GO7007_I2C_DEBUG | ||
| 988 | pr_debug("i2c read %d bytes on %02x\n", | ||
| 989 | msgs[i].len, msgs[i].addr); | ||
| 990 | #endif | ||
| 991 | buf[0] = 0x01; | ||
| 992 | buf[1] = 1; | ||
| 993 | buf[2] = msgs[i].addr << 1; | ||
| 994 | buf[3] = msgs[i].len; | ||
| 995 | buf_len = 4; | ||
| 996 | } else { | ||
| 997 | #ifdef GO7007_I2C_DEBUG | ||
| 998 | pr_debug("i2c write %d bytes on %02x\n", | ||
| 999 | msgs[i].len, msgs[i].addr); | ||
| 1000 | #endif | ||
| 1001 | buf[0] = 0x00; | ||
| 1002 | buf[1] = msgs[i].len + 1; | ||
| 1003 | buf[2] = msgs[i].addr << 1; | ||
| 1004 | memcpy(&buf[3], msgs[i].buf, msgs[i].len); | ||
| 1005 | buf_len = msgs[i].len + 3; | ||
| 1006 | buf[buf_len++] = 0; | ||
| 1007 | } | ||
| 1008 | if (go7007_usb_vendor_request(go, 0x24, 0, 0, | ||
| 1009 | buf, buf_len, 0) < 0) | ||
| 1010 | goto i2c_done; | ||
| 1011 | if (msgs[i].flags & I2C_M_RD) { | ||
| 1012 | memset(buf, 0, msgs[i].len + 1); | ||
| 1013 | if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf, | ||
| 1014 | msgs[i].len + 1, 1) < 0) | ||
| 1015 | goto i2c_done; | ||
| 1016 | memcpy(msgs[i].buf, buf + 1, msgs[i].len); | ||
| 1017 | } | ||
| 1018 | } | ||
| 1019 | ret = num; | ||
| 1020 | |||
| 1021 | i2c_done: | ||
| 1022 | mutex_unlock(&usb->i2c_lock); | ||
| 1023 | return ret; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | static u32 go7007_usb_functionality(struct i2c_adapter *adapter) | ||
| 1027 | { | ||
| 1028 | /* No errors are reported by the hardware, so we don't bother | ||
| 1029 | * supporting quick writes to avoid confusing probing */ | ||
| 1030 | return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | static struct i2c_algorithm go7007_usb_algo = { | ||
| 1034 | .master_xfer = go7007_usb_i2c_master_xfer, | ||
| 1035 | .functionality = go7007_usb_functionality, | ||
| 1036 | }; | ||
| 1037 | |||
| 1038 | static struct i2c_adapter go7007_usb_adap_templ = { | ||
| 1039 | .owner = THIS_MODULE, | ||
| 1040 | .name = "WIS GO7007SB EZ-USB", | ||
| 1041 | .algo = &go7007_usb_algo, | ||
| 1042 | }; | ||
| 1043 | |||
| 1044 | /********************* USB add/remove functions *********************/ | ||
| 1045 | |||
| 1046 | static int go7007_usb_probe(struct usb_interface *intf, | ||
| 1047 | const struct usb_device_id *id) | ||
| 1048 | { | ||
| 1049 | struct go7007 *go; | ||
| 1050 | struct go7007_usb *usb; | ||
| 1051 | const struct go7007_usb_board *board; | ||
| 1052 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
| 1053 | unsigned num_i2c_devs; | ||
| 1054 | char *name; | ||
| 1055 | int video_pipe, i, v_urb_len; | ||
| 1056 | |||
| 1057 | pr_debug("probing new GO7007 USB board\n"); | ||
| 1058 | |||
| 1059 | switch (id->driver_info) { | ||
| 1060 | case GO7007_BOARDID_MATRIX_II: | ||
| 1061 | name = "WIS Matrix II or compatible"; | ||
| 1062 | board = &board_matrix_ii; | ||
| 1063 | break; | ||
| 1064 | case GO7007_BOARDID_MATRIX_RELOAD: | ||
| 1065 | name = "WIS Matrix Reloaded or compatible"; | ||
| 1066 | board = &board_matrix_reload; | ||
| 1067 | break; | ||
| 1068 | case GO7007_BOARDID_MATRIX_REV: | ||
| 1069 | name = "WIS Matrix Revolution or compatible"; | ||
| 1070 | board = &board_matrix_revolution; | ||
| 1071 | break; | ||
| 1072 | case GO7007_BOARDID_STAR_TREK: | ||
| 1073 | name = "WIS Star Trek or compatible"; | ||
| 1074 | board = &board_star_trek; | ||
| 1075 | break; | ||
| 1076 | case GO7007_BOARDID_XMEN: | ||
| 1077 | name = "WIS XMen or compatible"; | ||
| 1078 | board = &board_xmen; | ||
| 1079 | break; | ||
| 1080 | case GO7007_BOARDID_XMEN_II: | ||
| 1081 | name = "WIS XMen II or compatible"; | ||
| 1082 | board = &board_xmen; | ||
| 1083 | break; | ||
| 1084 | case GO7007_BOARDID_XMEN_III: | ||
| 1085 | name = "WIS XMen III or compatible"; | ||
| 1086 | board = &board_xmen; | ||
| 1087 | break; | ||
| 1088 | case GO7007_BOARDID_PX_M402U: | ||
| 1089 | name = "Plextor PX-M402U"; | ||
| 1090 | board = &board_matrix_ii; | ||
| 1091 | break; | ||
| 1092 | case GO7007_BOARDID_PX_TV402U: | ||
| 1093 | name = "Plextor PX-TV402U (unknown tuner)"; | ||
| 1094 | board = &board_px_tv402u; | ||
| 1095 | break; | ||
| 1096 | case GO7007_BOARDID_LIFEVIEW_LR192: | ||
| 1097 | dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n"); | ||
| 1098 | return -ENODEV; | ||
| 1099 | name = "Lifeview TV Walker Ultra"; | ||
| 1100 | board = &board_lifeview_lr192; | ||
| 1101 | break; | ||
| 1102 | case GO7007_BOARDID_SENSORAY_2250: | ||
| 1103 | dev_info(&intf->dev, "Sensoray 2250 found\n"); | ||
| 1104 | name = "Sensoray 2250/2251"; | ||
| 1105 | board = &board_sensoray_2250; | ||
| 1106 | break; | ||
| 1107 | case GO7007_BOARDID_ADS_USBAV_709: | ||
| 1108 | name = "ADS Tech DVD Xpress DX2"; | ||
| 1109 | board = &board_ads_usbav_709; | ||
| 1110 | break; | ||
| 1111 | default: | ||
| 1112 | dev_err(&intf->dev, "unknown board ID %d!\n", | ||
| 1113 | (unsigned int)id->driver_info); | ||
| 1114 | return -ENODEV; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | go = go7007_alloc(&board->main_info, &intf->dev); | ||
| 1118 | if (go == NULL) | ||
| 1119 | return -ENOMEM; | ||
| 1120 | |||
| 1121 | usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL); | ||
| 1122 | if (usb == NULL) { | ||
| 1123 | kfree(go); | ||
| 1124 | return -ENOMEM; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | usb->board = board; | ||
| 1128 | usb->usbdev = usbdev; | ||
| 1129 | usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info)); | ||
| 1130 | go->board_id = id->driver_info; | ||
| 1131 | strncpy(go->name, name, sizeof(go->name)); | ||
| 1132 | if (board->flags & GO7007_USB_EZUSB) | ||
| 1133 | go->hpi_ops = &go7007_usb_ezusb_hpi_ops; | ||
| 1134 | else | ||
| 1135 | go->hpi_ops = &go7007_usb_onboard_hpi_ops; | ||
| 1136 | go->hpi_context = usb; | ||
| 1137 | |||
| 1138 | /* Allocate the URB and buffer for receiving incoming interrupts */ | ||
| 1139 | usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1140 | if (usb->intr_urb == NULL) | ||
| 1141 | goto allocfail; | ||
| 1142 | usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); | ||
| 1143 | if (usb->intr_urb->transfer_buffer == NULL) | ||
| 1144 | goto allocfail; | ||
| 1145 | |||
| 1146 | if (go->board_id == GO7007_BOARDID_SENSORAY_2250) | ||
| 1147 | usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, | ||
| 1148 | usb_rcvbulkpipe(usb->usbdev, 4), | ||
| 1149 | usb->intr_urb->transfer_buffer, 2*sizeof(u16), | ||
| 1150 | go7007_usb_readinterrupt_complete, go); | ||
| 1151 | else | ||
| 1152 | usb_fill_int_urb(usb->intr_urb, usb->usbdev, | ||
| 1153 | usb_rcvintpipe(usb->usbdev, 4), | ||
| 1154 | usb->intr_urb->transfer_buffer, 2*sizeof(u16), | ||
| 1155 | go7007_usb_readinterrupt_complete, go, 8); | ||
| 1156 | usb_set_intfdata(intf, &go->v4l2_dev); | ||
| 1157 | |||
| 1158 | /* Boot the GO7007 */ | ||
| 1159 | if (go7007_boot_encoder(go, go->board_info->flags & | ||
| 1160 | GO7007_BOARD_USE_ONBOARD_I2C) < 0) | ||
| 1161 | goto allocfail; | ||
| 1162 | |||
| 1163 | /* Register the EZ-USB I2C adapter, if we're using it */ | ||
| 1164 | if (board->flags & GO7007_USB_EZUSB_I2C) { | ||
| 1165 | memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, | ||
| 1166 | sizeof(go7007_usb_adap_templ)); | ||
| 1167 | mutex_init(&usb->i2c_lock); | ||
| 1168 | go->i2c_adapter.dev.parent = go->dev; | ||
| 1169 | i2c_set_adapdata(&go->i2c_adapter, go); | ||
| 1170 | if (i2c_add_adapter(&go->i2c_adapter) < 0) { | ||
| 1171 | dev_err(go->dev, "error: i2c_add_adapter failed\n"); | ||
| 1172 | goto allocfail; | ||
| 1173 | } | ||
| 1174 | go->i2c_adapter_online = 1; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | /* Pelco and Adlink reused the XMen and XMen-III vendor and product | ||
| 1178 | * IDs for their own incompatible designs. We can detect XMen boards | ||
| 1179 | * by probing the sensor, but there is no way to probe the sensors on | ||
| 1180 | * the Pelco and Adlink designs so we default to the Adlink. If it | ||
| 1181 | * is actually a Pelco, the user must set the assume_endura module | ||
| 1182 | * parameter. */ | ||
| 1183 | if ((go->board_id == GO7007_BOARDID_XMEN || | ||
| 1184 | go->board_id == GO7007_BOARDID_XMEN_III) && | ||
| 1185 | go->i2c_adapter_online) { | ||
| 1186 | union i2c_smbus_data data; | ||
| 1187 | |||
| 1188 | /* Check to see if register 0x0A is 0x76 */ | ||
| 1189 | i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB, | ||
| 1190 | I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data); | ||
| 1191 | if (data.byte != 0x76) { | ||
| 1192 | if (assume_endura) { | ||
| 1193 | go->board_id = GO7007_BOARDID_ENDURA; | ||
| 1194 | usb->board = board = &board_endura; | ||
| 1195 | go->board_info = &board->main_info; | ||
| 1196 | strncpy(go->name, "Pelco Endura", | ||
| 1197 | sizeof(go->name)); | ||
| 1198 | } else { | ||
| 1199 | u16 channel; | ||
| 1200 | |||
| 1201 | /* read channel number from GPIO[1:0] */ | ||
| 1202 | go7007_read_addr(go, 0x3c81, &channel); | ||
| 1203 | channel &= 0x3; | ||
| 1204 | go->board_id = GO7007_BOARDID_ADLINK_MPG24; | ||
| 1205 | usb->board = board = &board_adlink_mpg24; | ||
| 1206 | go->board_info = &board->main_info; | ||
| 1207 | go->channel_number = channel; | ||
| 1208 | snprintf(go->name, sizeof(go->name), | ||
| 1209 | "Adlink PCI-MPG24, channel #%d", | ||
| 1210 | channel); | ||
| 1211 | } | ||
| 1212 | go7007_update_board(go); | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | num_i2c_devs = go->board_info->num_i2c_devs; | ||
| 1217 | |||
| 1218 | /* Probe the tuner model on the TV402U */ | ||
| 1219 | if (go->board_id == GO7007_BOARDID_PX_TV402U) { | ||
| 1220 | /* Board strapping indicates tuner model */ | ||
| 1221 | if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, | ||
| 1222 | 1) < 0) { | ||
| 1223 | dev_err(go->dev, "GPIO read failed!\n"); | ||
| 1224 | goto allocfail; | ||
| 1225 | } | ||
| 1226 | switch (go->usb_buf[0] >> 6) { | ||
| 1227 | case 1: | ||
| 1228 | go->tuner_type = TUNER_SONY_BTF_PG472Z; | ||
| 1229 | go->std = V4L2_STD_PAL; | ||
| 1230 | strncpy(go->name, "Plextor PX-TV402U-EU", | ||
| 1231 | sizeof(go->name)); | ||
| 1232 | break; | ||
| 1233 | case 2: | ||
| 1234 | go->tuner_type = TUNER_SONY_BTF_PK467Z; | ||
| 1235 | go->std = V4L2_STD_NTSC_M_JP; | ||
| 1236 | num_i2c_devs -= 2; | ||
| 1237 | strncpy(go->name, "Plextor PX-TV402U-JP", | ||
| 1238 | sizeof(go->name)); | ||
| 1239 | break; | ||
| 1240 | case 3: | ||
| 1241 | go->tuner_type = TUNER_SONY_BTF_PB463Z; | ||
| 1242 | num_i2c_devs -= 2; | ||
| 1243 | strncpy(go->name, "Plextor PX-TV402U-NA", | ||
| 1244 | sizeof(go->name)); | ||
| 1245 | break; | ||
| 1246 | default: | ||
| 1247 | pr_debug("unable to detect tuner type!\n"); | ||
| 1248 | break; | ||
| 1249 | } | ||
| 1250 | /* Configure tuner mode selection inputs connected | ||
| 1251 | * to the EZ-USB GPIO output pins */ | ||
| 1252 | if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, | ||
| 1253 | NULL, 0, 0) < 0) { | ||
| 1254 | dev_err(go->dev, "GPIO write failed!\n"); | ||
| 1255 | goto allocfail; | ||
| 1256 | } | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | /* Print a nasty message if the user attempts to use a USB2.0 device in | ||
| 1260 | * a USB1.1 port. There will be silent corruption of the stream. */ | ||
| 1261 | if ((board->flags & GO7007_USB_EZUSB) && | ||
| 1262 | usbdev->speed != USB_SPEED_HIGH) | ||
| 1263 | dev_err(go->dev, "*** WARNING *** This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n"); | ||
| 1264 | |||
| 1265 | /* Allocate the URBs and buffers for receiving the video stream */ | ||
| 1266 | if (board->flags & GO7007_USB_EZUSB) { | ||
| 1267 | v_urb_len = 1024; | ||
| 1268 | video_pipe = usb_rcvbulkpipe(usb->usbdev, 6); | ||
| 1269 | } else { | ||
| 1270 | v_urb_len = 512; | ||
| 1271 | video_pipe = usb_rcvbulkpipe(usb->usbdev, 1); | ||
| 1272 | } | ||
| 1273 | for (i = 0; i < 8; ++i) { | ||
| 1274 | usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1275 | if (usb->video_urbs[i] == NULL) | ||
| 1276 | goto allocfail; | ||
| 1277 | usb->video_urbs[i]->transfer_buffer = | ||
| 1278 | kmalloc(v_urb_len, GFP_KERNEL); | ||
| 1279 | if (usb->video_urbs[i]->transfer_buffer == NULL) | ||
| 1280 | goto allocfail; | ||
| 1281 | usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe, | ||
| 1282 | usb->video_urbs[i]->transfer_buffer, v_urb_len, | ||
| 1283 | go7007_usb_read_video_pipe_complete, go); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* Allocate the URBs and buffers for receiving the audio stream */ | ||
| 1287 | if ((board->flags & GO7007_USB_EZUSB) && | ||
| 1288 | (board->flags & GO7007_BOARD_HAS_AUDIO)) { | ||
| 1289 | for (i = 0; i < 8; ++i) { | ||
| 1290 | usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1291 | if (usb->audio_urbs[i] == NULL) | ||
| 1292 | goto allocfail; | ||
| 1293 | usb->audio_urbs[i]->transfer_buffer = kmalloc(4096, | ||
| 1294 | GFP_KERNEL); | ||
| 1295 | if (usb->audio_urbs[i]->transfer_buffer == NULL) | ||
| 1296 | goto allocfail; | ||
| 1297 | usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev, | ||
| 1298 | usb_rcvbulkpipe(usb->usbdev, 8), | ||
| 1299 | usb->audio_urbs[i]->transfer_buffer, 4096, | ||
| 1300 | go7007_usb_read_audio_pipe_complete, go); | ||
| 1301 | } | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | /* Do any final GO7007 initialization, then register the | ||
| 1305 | * V4L2 and ALSA interfaces */ | ||
| 1306 | if (go7007_register_encoder(go, num_i2c_devs) < 0) | ||
| 1307 | goto allocfail; | ||
| 1308 | |||
| 1309 | go->status = STATUS_ONLINE; | ||
| 1310 | return 0; | ||
| 1311 | |||
| 1312 | allocfail: | ||
| 1313 | go7007_usb_release(go); | ||
| 1314 | kfree(go); | ||
| 1315 | return -ENOMEM; | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | static void go7007_usb_disconnect(struct usb_interface *intf) | ||
| 1319 | { | ||
| 1320 | struct go7007 *go = to_go7007(usb_get_intfdata(intf)); | ||
| 1321 | |||
| 1322 | mutex_lock(&go->queue_lock); | ||
| 1323 | mutex_lock(&go->serialize_lock); | ||
| 1324 | |||
| 1325 | if (go->audio_enabled) | ||
| 1326 | go7007_snd_remove(go); | ||
| 1327 | |||
| 1328 | go->status = STATUS_SHUTDOWN; | ||
| 1329 | v4l2_device_disconnect(&go->v4l2_dev); | ||
| 1330 | video_unregister_device(&go->vdev); | ||
| 1331 | mutex_unlock(&go->serialize_lock); | ||
| 1332 | mutex_unlock(&go->queue_lock); | ||
| 1333 | |||
| 1334 | v4l2_device_put(&go->v4l2_dev); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static struct usb_driver go7007_usb_driver = { | ||
| 1338 | .name = "go7007", | ||
| 1339 | .probe = go7007_usb_probe, | ||
| 1340 | .disconnect = go7007_usb_disconnect, | ||
| 1341 | .id_table = go7007_usb_id_table, | ||
| 1342 | }; | ||
| 1343 | |||
| 1344 | module_usb_driver(go7007_usb_driver); | ||
| 1345 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c new file mode 100644 index 000000000000..ec799b4d88be --- /dev/null +++ b/drivers/media/usb/go7007/go7007-v4l2.c | |||
| @@ -0,0 +1,1173 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <linux/sched.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <linux/fs.h> | ||
| 20 | #include <linux/unistd.h> | ||
| 21 | #include <linux/time.h> | ||
| 22 | #include <linux/vmalloc.h> | ||
| 23 | #include <linux/pagemap.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/mutex.h> | ||
| 26 | #include <linux/uaccess.h> | ||
| 27 | #include <linux/videodev2.h> | ||
| 28 | #include <media/v4l2-common.h> | ||
| 29 | #include <media/v4l2-ioctl.h> | ||
| 30 | #include <media/v4l2-subdev.h> | ||
| 31 | #include <media/v4l2-event.h> | ||
| 32 | #include <media/videobuf2-vmalloc.h> | ||
| 33 | #include <media/saa7115.h> | ||
| 34 | |||
| 35 | #include "go7007-priv.h" | ||
| 36 | |||
| 37 | #define call_all(dev, o, f, args...) \ | ||
| 38 | v4l2_device_call_until_err(dev, 0, o, f, ##args) | ||
| 39 | |||
| 40 | static bool valid_pixelformat(u32 pixelformat) | ||
| 41 | { | ||
| 42 | switch (pixelformat) { | ||
| 43 | case V4L2_PIX_FMT_MJPEG: | ||
| 44 | case V4L2_PIX_FMT_MPEG1: | ||
| 45 | case V4L2_PIX_FMT_MPEG2: | ||
| 46 | case V4L2_PIX_FMT_MPEG4: | ||
| 47 | return true; | ||
| 48 | default: | ||
| 49 | return false; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | static u32 get_frame_type_flag(struct go7007_buffer *vb, int format) | ||
| 54 | { | ||
| 55 | u8 *ptr = vb2_plane_vaddr(&vb->vb, 0); | ||
| 56 | |||
| 57 | switch (format) { | ||
| 58 | case V4L2_PIX_FMT_MJPEG: | ||
| 59 | return V4L2_BUF_FLAG_KEYFRAME; | ||
| 60 | case V4L2_PIX_FMT_MPEG4: | ||
| 61 | switch ((ptr[vb->frame_offset + 4] >> 6) & 0x3) { | ||
| 62 | case 0: | ||
| 63 | return V4L2_BUF_FLAG_KEYFRAME; | ||
| 64 | case 1: | ||
| 65 | return V4L2_BUF_FLAG_PFRAME; | ||
| 66 | case 2: | ||
| 67 | return V4L2_BUF_FLAG_BFRAME; | ||
| 68 | default: | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | case V4L2_PIX_FMT_MPEG1: | ||
| 72 | case V4L2_PIX_FMT_MPEG2: | ||
| 73 | switch ((ptr[vb->frame_offset + 5] >> 3) & 0x7) { | ||
| 74 | case 1: | ||
| 75 | return V4L2_BUF_FLAG_KEYFRAME; | ||
| 76 | case 2: | ||
| 77 | return V4L2_BUF_FLAG_PFRAME; | ||
| 78 | case 3: | ||
| 79 | return V4L2_BUF_FLAG_BFRAME; | ||
| 80 | default: | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static void get_resolution(struct go7007 *go, int *width, int *height) | ||
| 89 | { | ||
| 90 | switch (go->standard) { | ||
| 91 | case GO7007_STD_NTSC: | ||
| 92 | *width = 720; | ||
| 93 | *height = 480; | ||
| 94 | break; | ||
| 95 | case GO7007_STD_PAL: | ||
| 96 | *width = 720; | ||
| 97 | *height = 576; | ||
| 98 | break; | ||
| 99 | case GO7007_STD_OTHER: | ||
| 100 | default: | ||
| 101 | *width = go->board_info->sensor_width; | ||
| 102 | *height = go->board_info->sensor_height; | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | static void set_formatting(struct go7007 *go) | ||
| 108 | { | ||
| 109 | if (go->format == V4L2_PIX_FMT_MJPEG) { | ||
| 110 | go->pali = 0; | ||
| 111 | go->aspect_ratio = GO7007_RATIO_1_1; | ||
| 112 | go->gop_size = 0; | ||
| 113 | go->ipb = 0; | ||
| 114 | go->closed_gop = 0; | ||
| 115 | go->repeat_seqhead = 0; | ||
| 116 | go->seq_header_enable = 0; | ||
| 117 | go->gop_header_enable = 0; | ||
| 118 | go->dvd_mode = 0; | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | |||
| 122 | switch (go->format) { | ||
| 123 | case V4L2_PIX_FMT_MPEG1: | ||
| 124 | go->pali = 0; | ||
| 125 | break; | ||
| 126 | default: | ||
| 127 | case V4L2_PIX_FMT_MPEG2: | ||
| 128 | go->pali = 0x48; | ||
| 129 | break; | ||
| 130 | case V4L2_PIX_FMT_MPEG4: | ||
| 131 | /* For future reference: this is the list of MPEG4 | ||
| 132 | * profiles that are available, although they are | ||
| 133 | * untested: | ||
| 134 | * | ||
| 135 | * Profile pali | ||
| 136 | * -------------- ---- | ||
| 137 | * PROFILE_S_L0 0x08 | ||
| 138 | * PROFILE_S_L1 0x01 | ||
| 139 | * PROFILE_S_L2 0x02 | ||
| 140 | * PROFILE_S_L3 0x03 | ||
| 141 | * PROFILE_ARTS_L1 0x91 | ||
| 142 | * PROFILE_ARTS_L2 0x92 | ||
| 143 | * PROFILE_ARTS_L3 0x93 | ||
| 144 | * PROFILE_ARTS_L4 0x94 | ||
| 145 | * PROFILE_AS_L0 0xf0 | ||
| 146 | * PROFILE_AS_L1 0xf1 | ||
| 147 | * PROFILE_AS_L2 0xf2 | ||
| 148 | * PROFILE_AS_L3 0xf3 | ||
| 149 | * PROFILE_AS_L4 0xf4 | ||
| 150 | * PROFILE_AS_L5 0xf5 | ||
| 151 | */ | ||
| 152 | go->pali = 0xf5; | ||
| 153 | break; | ||
| 154 | } | ||
| 155 | go->gop_size = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_size); | ||
| 156 | go->closed_gop = v4l2_ctrl_g_ctrl(go->mpeg_video_gop_closure); | ||
| 157 | go->ipb = v4l2_ctrl_g_ctrl(go->mpeg_video_b_frames) != 0; | ||
| 158 | go->bitrate = v4l2_ctrl_g_ctrl(go->mpeg_video_bitrate); | ||
| 159 | go->repeat_seqhead = v4l2_ctrl_g_ctrl(go->mpeg_video_rep_seqheader); | ||
| 160 | go->gop_header_enable = 1; | ||
| 161 | go->dvd_mode = 0; | ||
| 162 | if (go->format == V4L2_PIX_FMT_MPEG2) | ||
| 163 | go->dvd_mode = | ||
| 164 | go->bitrate == 9800000 && | ||
| 165 | go->gop_size == 15 && | ||
| 166 | go->ipb == 0 && | ||
| 167 | go->repeat_seqhead == 1 && | ||
| 168 | go->closed_gop; | ||
| 169 | |||
| 170 | switch (v4l2_ctrl_g_ctrl(go->mpeg_video_aspect_ratio)) { | ||
| 171 | default: | ||
| 172 | case V4L2_MPEG_VIDEO_ASPECT_1x1: | ||
| 173 | go->aspect_ratio = GO7007_RATIO_1_1; | ||
| 174 | break; | ||
| 175 | case V4L2_MPEG_VIDEO_ASPECT_4x3: | ||
| 176 | go->aspect_ratio = GO7007_RATIO_4_3; | ||
| 177 | break; | ||
| 178 | case V4L2_MPEG_VIDEO_ASPECT_16x9: | ||
| 179 | go->aspect_ratio = GO7007_RATIO_16_9; | ||
| 180 | break; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try) | ||
| 185 | { | ||
| 186 | int sensor_height = 0, sensor_width = 0; | ||
| 187 | int width, height; | ||
| 188 | |||
| 189 | if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat)) | ||
| 190 | return -EINVAL; | ||
| 191 | |||
| 192 | get_resolution(go, &sensor_width, &sensor_height); | ||
| 193 | |||
| 194 | if (fmt == NULL) { | ||
| 195 | width = sensor_width; | ||
| 196 | height = sensor_height; | ||
| 197 | } else if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { | ||
| 198 | if (fmt->fmt.pix.width > sensor_width) | ||
| 199 | width = sensor_width; | ||
| 200 | else if (fmt->fmt.pix.width < 144) | ||
| 201 | width = 144; | ||
| 202 | else | ||
| 203 | width = fmt->fmt.pix.width & ~0x0f; | ||
| 204 | |||
| 205 | if (fmt->fmt.pix.height > sensor_height) | ||
| 206 | height = sensor_height; | ||
| 207 | else if (fmt->fmt.pix.height < 96) | ||
| 208 | height = 96; | ||
| 209 | else | ||
| 210 | height = fmt->fmt.pix.height & ~0x0f; | ||
| 211 | } else { | ||
| 212 | width = fmt->fmt.pix.width; | ||
| 213 | |||
| 214 | if (width <= sensor_width / 4) { | ||
| 215 | width = sensor_width / 4; | ||
| 216 | height = sensor_height / 4; | ||
| 217 | } else if (width <= sensor_width / 2) { | ||
| 218 | width = sensor_width / 2; | ||
| 219 | height = sensor_height / 2; | ||
| 220 | } else { | ||
| 221 | width = sensor_width; | ||
| 222 | height = sensor_height; | ||
| 223 | } | ||
| 224 | width &= ~0xf; | ||
| 225 | height &= ~0xf; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (fmt != NULL) { | ||
| 229 | u32 pixelformat = fmt->fmt.pix.pixelformat; | ||
| 230 | |||
| 231 | memset(fmt, 0, sizeof(*fmt)); | ||
| 232 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 233 | fmt->fmt.pix.width = width; | ||
| 234 | fmt->fmt.pix.height = height; | ||
| 235 | fmt->fmt.pix.pixelformat = pixelformat; | ||
| 236 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
| 237 | fmt->fmt.pix.bytesperline = 0; | ||
| 238 | fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE; | ||
| 239 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
| 240 | } | ||
| 241 | |||
| 242 | if (try) | ||
| 243 | return 0; | ||
| 244 | |||
| 245 | if (fmt) | ||
| 246 | go->format = fmt->fmt.pix.pixelformat; | ||
| 247 | go->width = width; | ||
| 248 | go->height = height; | ||
| 249 | go->encoder_h_offset = go->board_info->sensor_h_offset; | ||
| 250 | go->encoder_v_offset = go->board_info->sensor_v_offset; | ||
| 251 | |||
| 252 | if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) { | ||
| 253 | struct v4l2_mbus_framefmt mbus_fmt; | ||
| 254 | |||
| 255 | mbus_fmt.code = V4L2_MBUS_FMT_FIXED; | ||
| 256 | mbus_fmt.width = fmt ? fmt->fmt.pix.width : width; | ||
| 257 | mbus_fmt.height = height; | ||
| 258 | go->encoder_h_halve = 0; | ||
| 259 | go->encoder_v_halve = 0; | ||
| 260 | go->encoder_subsample = 0; | ||
| 261 | call_all(&go->v4l2_dev, video, s_mbus_fmt, &mbus_fmt); | ||
| 262 | } else { | ||
| 263 | if (width <= sensor_width / 4) { | ||
| 264 | go->encoder_h_halve = 1; | ||
| 265 | go->encoder_v_halve = 1; | ||
| 266 | go->encoder_subsample = 1; | ||
| 267 | } else if (width <= sensor_width / 2) { | ||
| 268 | go->encoder_h_halve = 1; | ||
| 269 | go->encoder_v_halve = 1; | ||
| 270 | go->encoder_subsample = 0; | ||
| 271 | } else { | ||
| 272 | go->encoder_h_halve = 0; | ||
| 273 | go->encoder_v_halve = 0; | ||
| 274 | go->encoder_subsample = 0; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int vidioc_querycap(struct file *file, void *priv, | ||
| 281 | struct v4l2_capability *cap) | ||
| 282 | { | ||
| 283 | struct go7007 *go = video_drvdata(file); | ||
| 284 | |||
| 285 | strlcpy(cap->driver, "go7007", sizeof(cap->driver)); | ||
| 286 | strlcpy(cap->card, go->name, sizeof(cap->card)); | ||
| 287 | strlcpy(cap->bus_info, go->bus_info, sizeof(cap->bus_info)); | ||
| 288 | |||
| 289 | cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | | ||
| 290 | V4L2_CAP_STREAMING; | ||
| 291 | |||
| 292 | if (go->board_info->num_aud_inputs) | ||
| 293 | cap->device_caps |= V4L2_CAP_AUDIO; | ||
| 294 | if (go->board_info->flags & GO7007_BOARD_HAS_TUNER) | ||
| 295 | cap->device_caps |= V4L2_CAP_TUNER; | ||
| 296 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
| 301 | struct v4l2_fmtdesc *fmt) | ||
| 302 | { | ||
| 303 | char *desc = NULL; | ||
| 304 | |||
| 305 | switch (fmt->index) { | ||
| 306 | case 0: | ||
| 307 | fmt->pixelformat = V4L2_PIX_FMT_MJPEG; | ||
| 308 | desc = "Motion JPEG"; | ||
| 309 | break; | ||
| 310 | case 1: | ||
| 311 | fmt->pixelformat = V4L2_PIX_FMT_MPEG1; | ||
| 312 | desc = "MPEG-1 ES"; | ||
| 313 | break; | ||
| 314 | case 2: | ||
| 315 | fmt->pixelformat = V4L2_PIX_FMT_MPEG2; | ||
| 316 | desc = "MPEG-2 ES"; | ||
| 317 | break; | ||
| 318 | case 3: | ||
| 319 | fmt->pixelformat = V4L2_PIX_FMT_MPEG4; | ||
| 320 | desc = "MPEG-4 ES"; | ||
| 321 | break; | ||
| 322 | default: | ||
| 323 | return -EINVAL; | ||
| 324 | } | ||
| 325 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 326 | fmt->flags = V4L2_FMT_FLAG_COMPRESSED; | ||
| 327 | |||
| 328 | strncpy(fmt->description, desc, sizeof(fmt->description)); | ||
| 329 | |||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
| 334 | struct v4l2_format *fmt) | ||
| 335 | { | ||
| 336 | struct go7007 *go = video_drvdata(file); | ||
| 337 | |||
| 338 | fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 339 | fmt->fmt.pix.width = go->width; | ||
| 340 | fmt->fmt.pix.height = go->height; | ||
| 341 | fmt->fmt.pix.pixelformat = go->format; | ||
| 342 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
| 343 | fmt->fmt.pix.bytesperline = 0; | ||
| 344 | fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE; | ||
| 345 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
| 346 | |||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | |||
| 350 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||
| 351 | struct v4l2_format *fmt) | ||
| 352 | { | ||
| 353 | struct go7007 *go = video_drvdata(file); | ||
| 354 | |||
| 355 | return set_capture_size(go, fmt, 1); | ||
| 356 | } | ||
| 357 | |||
| 358 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | ||
| 359 | struct v4l2_format *fmt) | ||
| 360 | { | ||
| 361 | struct go7007 *go = video_drvdata(file); | ||
| 362 | |||
| 363 | if (vb2_is_busy(&go->vidq)) | ||
| 364 | return -EBUSY; | ||
| 365 | |||
| 366 | return set_capture_size(go, fmt, 0); | ||
| 367 | } | ||
| 368 | |||
| 369 | static int go7007_queue_setup(struct vb2_queue *q, | ||
| 370 | const struct v4l2_format *fmt, | ||
| 371 | unsigned int *num_buffers, unsigned int *num_planes, | ||
| 372 | unsigned int sizes[], void *alloc_ctxs[]) | ||
| 373 | { | ||
| 374 | sizes[0] = GO7007_BUF_SIZE; | ||
| 375 | *num_planes = 1; | ||
| 376 | |||
| 377 | if (*num_buffers < 2) | ||
| 378 | *num_buffers = 2; | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static void go7007_buf_queue(struct vb2_buffer *vb) | ||
| 384 | { | ||
| 385 | struct vb2_queue *vq = vb->vb2_queue; | ||
| 386 | struct go7007 *go = vb2_get_drv_priv(vq); | ||
| 387 | struct go7007_buffer *go7007_vb = | ||
| 388 | container_of(vb, struct go7007_buffer, vb); | ||
| 389 | unsigned long flags; | ||
| 390 | |||
| 391 | spin_lock_irqsave(&go->spinlock, flags); | ||
| 392 | list_add_tail(&go7007_vb->list, &go->vidq_active); | ||
| 393 | spin_unlock_irqrestore(&go->spinlock, flags); | ||
| 394 | } | ||
| 395 | |||
| 396 | static int go7007_buf_prepare(struct vb2_buffer *vb) | ||
| 397 | { | ||
| 398 | struct go7007_buffer *go7007_vb = | ||
| 399 | container_of(vb, struct go7007_buffer, vb); | ||
| 400 | |||
| 401 | go7007_vb->modet_active = 0; | ||
| 402 | go7007_vb->frame_offset = 0; | ||
| 403 | vb->v4l2_planes[0].bytesused = 0; | ||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | static void go7007_buf_finish(struct vb2_buffer *vb) | ||
| 408 | { | ||
| 409 | struct vb2_queue *vq = vb->vb2_queue; | ||
| 410 | struct go7007 *go = vb2_get_drv_priv(vq); | ||
| 411 | struct go7007_buffer *go7007_vb = | ||
| 412 | container_of(vb, struct go7007_buffer, vb); | ||
| 413 | u32 frame_type_flag = get_frame_type_flag(go7007_vb, go->format); | ||
| 414 | struct v4l2_buffer *buf = &vb->v4l2_buf; | ||
| 415 | |||
| 416 | buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_BFRAME | | ||
| 417 | V4L2_BUF_FLAG_PFRAME); | ||
| 418 | buf->flags |= frame_type_flag; | ||
| 419 | buf->field = V4L2_FIELD_NONE; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int go7007_start_streaming(struct vb2_queue *q, unsigned int count) | ||
| 423 | { | ||
| 424 | struct go7007 *go = vb2_get_drv_priv(q); | ||
| 425 | int ret; | ||
| 426 | |||
| 427 | set_formatting(go); | ||
| 428 | mutex_lock(&go->hw_lock); | ||
| 429 | go->next_seq = 0; | ||
| 430 | go->active_buf = NULL; | ||
| 431 | go->modet_event_status = 0; | ||
| 432 | q->streaming = 1; | ||
| 433 | if (go7007_start_encoder(go) < 0) | ||
| 434 | ret = -EIO; | ||
| 435 | else | ||
| 436 | ret = 0; | ||
| 437 | mutex_unlock(&go->hw_lock); | ||
| 438 | if (ret) { | ||
| 439 | q->streaming = 0; | ||
| 440 | return ret; | ||
| 441 | } | ||
| 442 | call_all(&go->v4l2_dev, video, s_stream, 1); | ||
| 443 | v4l2_ctrl_grab(go->mpeg_video_gop_size, true); | ||
| 444 | v4l2_ctrl_grab(go->mpeg_video_gop_closure, true); | ||
| 445 | v4l2_ctrl_grab(go->mpeg_video_bitrate, true); | ||
| 446 | v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, true); | ||
| 447 | /* Turn on Capture LED */ | ||
| 448 | if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) | ||
| 449 | go7007_write_addr(go, 0x3c82, 0x0005); | ||
| 450 | return ret; | ||
| 451 | } | ||
| 452 | |||
| 453 | static void go7007_stop_streaming(struct vb2_queue *q) | ||
| 454 | { | ||
| 455 | struct go7007 *go = vb2_get_drv_priv(q); | ||
| 456 | unsigned long flags; | ||
| 457 | |||
| 458 | q->streaming = 0; | ||
| 459 | go7007_stream_stop(go); | ||
| 460 | mutex_lock(&go->hw_lock); | ||
| 461 | go7007_reset_encoder(go); | ||
| 462 | mutex_unlock(&go->hw_lock); | ||
| 463 | call_all(&go->v4l2_dev, video, s_stream, 0); | ||
| 464 | |||
| 465 | spin_lock_irqsave(&go->spinlock, flags); | ||
| 466 | INIT_LIST_HEAD(&go->vidq_active); | ||
| 467 | spin_unlock_irqrestore(&go->spinlock, flags); | ||
| 468 | v4l2_ctrl_grab(go->mpeg_video_gop_size, false); | ||
| 469 | v4l2_ctrl_grab(go->mpeg_video_gop_closure, false); | ||
| 470 | v4l2_ctrl_grab(go->mpeg_video_bitrate, false); | ||
| 471 | v4l2_ctrl_grab(go->mpeg_video_aspect_ratio, false); | ||
| 472 | /* Turn on Capture LED */ | ||
| 473 | if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) | ||
| 474 | go7007_write_addr(go, 0x3c82, 0x000d); | ||
| 475 | } | ||
| 476 | |||
| 477 | static struct vb2_ops go7007_video_qops = { | ||
| 478 | .queue_setup = go7007_queue_setup, | ||
| 479 | .buf_queue = go7007_buf_queue, | ||
| 480 | .buf_prepare = go7007_buf_prepare, | ||
| 481 | .buf_finish = go7007_buf_finish, | ||
| 482 | .start_streaming = go7007_start_streaming, | ||
| 483 | .stop_streaming = go7007_stop_streaming, | ||
| 484 | .wait_prepare = vb2_ops_wait_prepare, | ||
| 485 | .wait_finish = vb2_ops_wait_finish, | ||
| 486 | }; | ||
| 487 | |||
| 488 | static int vidioc_g_parm(struct file *filp, void *priv, | ||
| 489 | struct v4l2_streamparm *parm) | ||
| 490 | { | ||
| 491 | struct go7007 *go = video_drvdata(filp); | ||
| 492 | struct v4l2_fract timeperframe = { | ||
| 493 | .numerator = 1001 * go->fps_scale, | ||
| 494 | .denominator = go->sensor_framerate, | ||
| 495 | }; | ||
| 496 | |||
| 497 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 498 | return -EINVAL; | ||
| 499 | |||
| 500 | parm->parm.capture.readbuffers = 2; | ||
| 501 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
| 502 | parm->parm.capture.timeperframe = timeperframe; | ||
| 503 | |||
| 504 | return 0; | ||
| 505 | } | ||
| 506 | |||
| 507 | static int vidioc_s_parm(struct file *filp, void *priv, | ||
| 508 | struct v4l2_streamparm *parm) | ||
| 509 | { | ||
| 510 | struct go7007 *go = video_drvdata(filp); | ||
| 511 | unsigned int n, d; | ||
| 512 | |||
| 513 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 514 | return -EINVAL; | ||
| 515 | |||
| 516 | n = go->sensor_framerate * | ||
| 517 | parm->parm.capture.timeperframe.numerator; | ||
| 518 | d = 1001 * parm->parm.capture.timeperframe.denominator; | ||
| 519 | if (n != 0 && d != 0 && n > d) | ||
| 520 | go->fps_scale = (n + d/2) / d; | ||
| 521 | else | ||
| 522 | go->fps_scale = 1; | ||
| 523 | |||
| 524 | return vidioc_g_parm(filp, priv, parm); | ||
| 525 | } | ||
| 526 | |||
| 527 | /* VIDIOC_ENUMSTD on go7007 were used for enumerating the supported fps and | ||
| 528 | its resolution, when the device is not connected to TV. | ||
| 529 | This is were an API abuse, probably used by the lack of specific IOCTL's to | ||
| 530 | enumerate it, by the time the driver was written. | ||
| 531 | |||
| 532 | However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS | ||
| 533 | and VIDIOC_ENUM_FRAMESIZES) were added for this purpose. | ||
| 534 | |||
| 535 | The two functions below implement the newer ioctls | ||
| 536 | */ | ||
| 537 | static int vidioc_enum_framesizes(struct file *filp, void *priv, | ||
| 538 | struct v4l2_frmsizeenum *fsize) | ||
| 539 | { | ||
| 540 | struct go7007 *go = video_drvdata(filp); | ||
| 541 | int width, height; | ||
| 542 | |||
| 543 | if (fsize->index > 2) | ||
| 544 | return -EINVAL; | ||
| 545 | |||
| 546 | if (!valid_pixelformat(fsize->pixel_format)) | ||
| 547 | return -EINVAL; | ||
| 548 | |||
| 549 | get_resolution(go, &width, &height); | ||
| 550 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
| 551 | fsize->discrete.width = (width >> fsize->index) & ~0xf; | ||
| 552 | fsize->discrete.height = (height >> fsize->index) & ~0xf; | ||
| 553 | return 0; | ||
| 554 | } | ||
| 555 | |||
| 556 | static int vidioc_enum_frameintervals(struct file *filp, void *priv, | ||
| 557 | struct v4l2_frmivalenum *fival) | ||
| 558 | { | ||
| 559 | struct go7007 *go = video_drvdata(filp); | ||
| 560 | int width, height; | ||
| 561 | int i; | ||
| 562 | |||
| 563 | if (fival->index > 4) | ||
| 564 | return -EINVAL; | ||
| 565 | |||
| 566 | if (!valid_pixelformat(fival->pixel_format)) | ||
| 567 | return -EINVAL; | ||
| 568 | |||
| 569 | if (!(go->board_info->sensor_flags & GO7007_SENSOR_SCALING)) { | ||
| 570 | get_resolution(go, &width, &height); | ||
| 571 | for (i = 0; i <= 2; i++) | ||
| 572 | if (fival->width == ((width >> i) & ~0xf) && | ||
| 573 | fival->height == ((height >> i) & ~0xf)) | ||
| 574 | break; | ||
| 575 | if (i > 2) | ||
| 576 | return -EINVAL; | ||
| 577 | } | ||
| 578 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; | ||
| 579 | fival->discrete.numerator = 1001 * (fival->index + 1); | ||
| 580 | fival->discrete.denominator = go->sensor_framerate; | ||
| 581 | return 0; | ||
| 582 | } | ||
| 583 | |||
| 584 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *std) | ||
| 585 | { | ||
| 586 | struct go7007 *go = video_drvdata(file); | ||
| 587 | |||
| 588 | *std = go->std; | ||
| 589 | return 0; | ||
| 590 | } | ||
| 591 | |||
| 592 | static int go7007_s_std(struct go7007 *go) | ||
| 593 | { | ||
| 594 | if (go->std & V4L2_STD_625_50) { | ||
| 595 | go->standard = GO7007_STD_PAL; | ||
| 596 | go->sensor_framerate = 25025; | ||
| 597 | } else { | ||
| 598 | go->standard = GO7007_STD_NTSC; | ||
| 599 | go->sensor_framerate = 30000; | ||
| 600 | } | ||
| 601 | |||
| 602 | call_all(&go->v4l2_dev, video, s_std, go->std); | ||
| 603 | set_capture_size(go, NULL, 0); | ||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | |||
| 607 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id std) | ||
| 608 | { | ||
| 609 | struct go7007 *go = video_drvdata(file); | ||
| 610 | |||
| 611 | if (vb2_is_busy(&go->vidq)) | ||
| 612 | return -EBUSY; | ||
| 613 | |||
| 614 | go->std = std; | ||
| 615 | |||
| 616 | return go7007_s_std(go); | ||
| 617 | } | ||
| 618 | |||
| 619 | static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *std) | ||
| 620 | { | ||
| 621 | struct go7007 *go = video_drvdata(file); | ||
| 622 | |||
| 623 | return call_all(&go->v4l2_dev, video, querystd, std); | ||
| 624 | } | ||
| 625 | |||
| 626 | static int vidioc_enum_input(struct file *file, void *priv, | ||
| 627 | struct v4l2_input *inp) | ||
| 628 | { | ||
| 629 | struct go7007 *go = video_drvdata(file); | ||
| 630 | |||
| 631 | if (inp->index >= go->board_info->num_inputs) | ||
| 632 | return -EINVAL; | ||
| 633 | |||
| 634 | strncpy(inp->name, go->board_info->inputs[inp->index].name, | ||
| 635 | sizeof(inp->name)); | ||
| 636 | |||
| 637 | /* If this board has a tuner, it will be the first input */ | ||
| 638 | if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) && | ||
| 639 | inp->index == 0) | ||
| 640 | inp->type = V4L2_INPUT_TYPE_TUNER; | ||
| 641 | else | ||
| 642 | inp->type = V4L2_INPUT_TYPE_CAMERA; | ||
| 643 | |||
| 644 | if (go->board_info->num_aud_inputs) | ||
| 645 | inp->audioset = (1 << go->board_info->num_aud_inputs) - 1; | ||
| 646 | else | ||
| 647 | inp->audioset = 0; | ||
| 648 | inp->tuner = 0; | ||
| 649 | if (go->board_info->sensor_flags & GO7007_SENSOR_TV) | ||
| 650 | inp->std = video_devdata(file)->tvnorms; | ||
| 651 | else | ||
| 652 | inp->std = 0; | ||
| 653 | |||
| 654 | return 0; | ||
| 655 | } | ||
| 656 | |||
| 657 | |||
| 658 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *input) | ||
| 659 | { | ||
| 660 | struct go7007 *go = video_drvdata(file); | ||
| 661 | |||
| 662 | *input = go->input; | ||
| 663 | |||
| 664 | return 0; | ||
| 665 | } | ||
| 666 | |||
| 667 | static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a) | ||
| 668 | { | ||
| 669 | struct go7007 *go = video_drvdata(file); | ||
| 670 | |||
| 671 | if (a->index >= go->board_info->num_aud_inputs) | ||
| 672 | return -EINVAL; | ||
| 673 | strlcpy(a->name, go->board_info->aud_inputs[a->index].name, | ||
| 674 | sizeof(a->name)); | ||
| 675 | a->capability = V4L2_AUDCAP_STEREO; | ||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a) | ||
| 680 | { | ||
| 681 | struct go7007 *go = video_drvdata(file); | ||
| 682 | |||
| 683 | a->index = go->aud_input; | ||
| 684 | strlcpy(a->name, go->board_info->aud_inputs[go->aud_input].name, | ||
| 685 | sizeof(a->name)); | ||
| 686 | a->capability = V4L2_AUDCAP_STEREO; | ||
| 687 | return 0; | ||
| 688 | } | ||
| 689 | |||
| 690 | static int vidioc_s_audio(struct file *file, void *fh, | ||
| 691 | const struct v4l2_audio *a) | ||
| 692 | { | ||
| 693 | struct go7007 *go = video_drvdata(file); | ||
| 694 | |||
| 695 | if (a->index >= go->board_info->num_aud_inputs) | ||
| 696 | return -EINVAL; | ||
| 697 | go->aud_input = a->index; | ||
| 698 | v4l2_subdev_call(go->sd_audio, audio, s_routing, | ||
| 699 | go->board_info->aud_inputs[go->aud_input].audio_input, 0, 0); | ||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | static void go7007_s_input(struct go7007 *go) | ||
| 704 | { | ||
| 705 | unsigned int input = go->input; | ||
| 706 | |||
| 707 | v4l2_subdev_call(go->sd_video, video, s_routing, | ||
| 708 | go->board_info->inputs[input].video_input, 0, | ||
| 709 | go->board_info->video_config); | ||
| 710 | if (go->board_info->num_aud_inputs) { | ||
| 711 | int aud_input = go->board_info->inputs[input].audio_index; | ||
| 712 | |||
| 713 | v4l2_subdev_call(go->sd_audio, audio, s_routing, | ||
| 714 | go->board_info->aud_inputs[aud_input].audio_input, 0, 0); | ||
| 715 | go->aud_input = aud_input; | ||
| 716 | } | ||
| 717 | } | ||
| 718 | |||
| 719 | static int vidioc_s_input(struct file *file, void *priv, unsigned int input) | ||
| 720 | { | ||
| 721 | struct go7007 *go = video_drvdata(file); | ||
| 722 | |||
| 723 | if (input >= go->board_info->num_inputs) | ||
| 724 | return -EINVAL; | ||
| 725 | if (vb2_is_busy(&go->vidq)) | ||
| 726 | return -EBUSY; | ||
| 727 | |||
| 728 | go->input = input; | ||
| 729 | go7007_s_input(go); | ||
| 730 | |||
| 731 | return 0; | ||
| 732 | } | ||
| 733 | |||
| 734 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
| 735 | struct v4l2_tuner *t) | ||
| 736 | { | ||
| 737 | struct go7007 *go = video_drvdata(file); | ||
| 738 | |||
| 739 | if (t->index != 0) | ||
| 740 | return -EINVAL; | ||
| 741 | |||
| 742 | strlcpy(t->name, "Tuner", sizeof(t->name)); | ||
| 743 | return call_all(&go->v4l2_dev, tuner, g_tuner, t); | ||
| 744 | } | ||
| 745 | |||
| 746 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
| 747 | const struct v4l2_tuner *t) | ||
| 748 | { | ||
| 749 | struct go7007 *go = video_drvdata(file); | ||
| 750 | |||
| 751 | if (t->index != 0) | ||
| 752 | return -EINVAL; | ||
| 753 | |||
| 754 | return call_all(&go->v4l2_dev, tuner, s_tuner, t); | ||
| 755 | } | ||
| 756 | |||
| 757 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
| 758 | struct v4l2_frequency *f) | ||
| 759 | { | ||
| 760 | struct go7007 *go = video_drvdata(file); | ||
| 761 | |||
| 762 | if (f->tuner) | ||
| 763 | return -EINVAL; | ||
| 764 | |||
| 765 | return call_all(&go->v4l2_dev, tuner, g_frequency, f); | ||
| 766 | } | ||
| 767 | |||
| 768 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
| 769 | const struct v4l2_frequency *f) | ||
| 770 | { | ||
| 771 | struct go7007 *go = video_drvdata(file); | ||
| 772 | |||
| 773 | if (f->tuner) | ||
| 774 | return -EINVAL; | ||
| 775 | |||
| 776 | return call_all(&go->v4l2_dev, tuner, s_frequency, f); | ||
| 777 | } | ||
| 778 | |||
| 779 | static int vidioc_log_status(struct file *file, void *priv) | ||
| 780 | { | ||
| 781 | struct go7007 *go = video_drvdata(file); | ||
| 782 | |||
| 783 | v4l2_ctrl_log_status(file, priv); | ||
| 784 | return call_all(&go->v4l2_dev, core, log_status); | ||
| 785 | } | ||
| 786 | |||
| 787 | static int vidioc_subscribe_event(struct v4l2_fh *fh, | ||
| 788 | const struct v4l2_event_subscription *sub) | ||
| 789 | { | ||
| 790 | |||
| 791 | switch (sub->type) { | ||
| 792 | case V4L2_EVENT_CTRL: | ||
| 793 | return v4l2_ctrl_subscribe_event(fh, sub); | ||
| 794 | case V4L2_EVENT_MOTION_DET: | ||
| 795 | /* Allow for up to 30 events (1 second for NTSC) to be | ||
| 796 | * stored. */ | ||
| 797 | return v4l2_event_subscribe(fh, sub, 30, NULL); | ||
| 798 | } | ||
| 799 | return -EINVAL; | ||
| 800 | } | ||
| 801 | |||
| 802 | |||
| 803 | static int go7007_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 804 | { | ||
| 805 | struct go7007 *go = | ||
| 806 | container_of(ctrl->handler, struct go7007, hdl); | ||
| 807 | unsigned y; | ||
| 808 | u8 *mt; | ||
| 809 | |||
| 810 | switch (ctrl->id) { | ||
| 811 | case V4L2_CID_PIXEL_THRESHOLD0: | ||
| 812 | go->modet[0].pixel_threshold = ctrl->val; | ||
| 813 | break; | ||
| 814 | case V4L2_CID_MOTION_THRESHOLD0: | ||
| 815 | go->modet[0].motion_threshold = ctrl->val; | ||
| 816 | break; | ||
| 817 | case V4L2_CID_MB_THRESHOLD0: | ||
| 818 | go->modet[0].mb_threshold = ctrl->val; | ||
| 819 | break; | ||
| 820 | case V4L2_CID_PIXEL_THRESHOLD1: | ||
| 821 | go->modet[1].pixel_threshold = ctrl->val; | ||
| 822 | break; | ||
| 823 | case V4L2_CID_MOTION_THRESHOLD1: | ||
| 824 | go->modet[1].motion_threshold = ctrl->val; | ||
| 825 | break; | ||
| 826 | case V4L2_CID_MB_THRESHOLD1: | ||
| 827 | go->modet[1].mb_threshold = ctrl->val; | ||
| 828 | break; | ||
| 829 | case V4L2_CID_PIXEL_THRESHOLD2: | ||
| 830 | go->modet[2].pixel_threshold = ctrl->val; | ||
| 831 | break; | ||
| 832 | case V4L2_CID_MOTION_THRESHOLD2: | ||
| 833 | go->modet[2].motion_threshold = ctrl->val; | ||
| 834 | break; | ||
| 835 | case V4L2_CID_MB_THRESHOLD2: | ||
| 836 | go->modet[2].mb_threshold = ctrl->val; | ||
| 837 | break; | ||
| 838 | case V4L2_CID_PIXEL_THRESHOLD3: | ||
| 839 | go->modet[3].pixel_threshold = ctrl->val; | ||
| 840 | break; | ||
| 841 | case V4L2_CID_MOTION_THRESHOLD3: | ||
| 842 | go->modet[3].motion_threshold = ctrl->val; | ||
| 843 | break; | ||
| 844 | case V4L2_CID_MB_THRESHOLD3: | ||
| 845 | go->modet[3].mb_threshold = ctrl->val; | ||
| 846 | break; | ||
| 847 | case V4L2_CID_DETECT_MD_REGION_GRID: | ||
| 848 | mt = go->modet_map; | ||
| 849 | for (y = 0; y < go->height / 16; y++, mt += go->width / 16) | ||
| 850 | memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16); | ||
| 851 | break; | ||
| 852 | default: | ||
| 853 | return -EINVAL; | ||
| 854 | } | ||
| 855 | return 0; | ||
| 856 | } | ||
| 857 | |||
| 858 | static struct v4l2_file_operations go7007_fops = { | ||
| 859 | .owner = THIS_MODULE, | ||
| 860 | .open = v4l2_fh_open, | ||
| 861 | .release = vb2_fop_release, | ||
| 862 | .unlocked_ioctl = video_ioctl2, | ||
| 863 | .read = vb2_fop_read, | ||
| 864 | .mmap = vb2_fop_mmap, | ||
| 865 | .poll = vb2_fop_poll, | ||
| 866 | }; | ||
| 867 | |||
| 868 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | ||
| 869 | .vidioc_querycap = vidioc_querycap, | ||
| 870 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | ||
| 871 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | ||
| 872 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | ||
| 873 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | ||
| 874 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | ||
| 875 | .vidioc_querybuf = vb2_ioctl_querybuf, | ||
| 876 | .vidioc_qbuf = vb2_ioctl_qbuf, | ||
| 877 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | ||
| 878 | .vidioc_g_std = vidioc_g_std, | ||
| 879 | .vidioc_s_std = vidioc_s_std, | ||
| 880 | .vidioc_querystd = vidioc_querystd, | ||
| 881 | .vidioc_enum_input = vidioc_enum_input, | ||
| 882 | .vidioc_g_input = vidioc_g_input, | ||
| 883 | .vidioc_s_input = vidioc_s_input, | ||
| 884 | .vidioc_enumaudio = vidioc_enumaudio, | ||
| 885 | .vidioc_g_audio = vidioc_g_audio, | ||
| 886 | .vidioc_s_audio = vidioc_s_audio, | ||
| 887 | .vidioc_streamon = vb2_ioctl_streamon, | ||
| 888 | .vidioc_streamoff = vb2_ioctl_streamoff, | ||
| 889 | .vidioc_g_tuner = vidioc_g_tuner, | ||
| 890 | .vidioc_s_tuner = vidioc_s_tuner, | ||
| 891 | .vidioc_g_frequency = vidioc_g_frequency, | ||
| 892 | .vidioc_s_frequency = vidioc_s_frequency, | ||
| 893 | .vidioc_g_parm = vidioc_g_parm, | ||
| 894 | .vidioc_s_parm = vidioc_s_parm, | ||
| 895 | .vidioc_enum_framesizes = vidioc_enum_framesizes, | ||
| 896 | .vidioc_enum_frameintervals = vidioc_enum_frameintervals, | ||
| 897 | .vidioc_log_status = vidioc_log_status, | ||
| 898 | .vidioc_subscribe_event = vidioc_subscribe_event, | ||
| 899 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
| 900 | }; | ||
| 901 | |||
| 902 | static struct video_device go7007_template = { | ||
| 903 | .name = "go7007", | ||
| 904 | .fops = &go7007_fops, | ||
| 905 | .release = video_device_release_empty, | ||
| 906 | .ioctl_ops = &video_ioctl_ops, | ||
| 907 | .tvnorms = V4L2_STD_ALL, | ||
| 908 | }; | ||
| 909 | |||
| 910 | static const struct v4l2_ctrl_ops go7007_ctrl_ops = { | ||
| 911 | .s_ctrl = go7007_s_ctrl, | ||
| 912 | }; | ||
| 913 | |||
| 914 | static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = { | ||
| 915 | .ops = &go7007_ctrl_ops, | ||
| 916 | .id = V4L2_CID_PIXEL_THRESHOLD0, | ||
| 917 | .name = "Pixel Threshold Region 0", | ||
| 918 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 919 | .def = 20, | ||
| 920 | .max = 32767, | ||
| 921 | .step = 1, | ||
| 922 | }; | ||
| 923 | |||
| 924 | static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = { | ||
| 925 | .ops = &go7007_ctrl_ops, | ||
| 926 | .id = V4L2_CID_MOTION_THRESHOLD0, | ||
| 927 | .name = "Motion Threshold Region 0", | ||
| 928 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 929 | .def = 80, | ||
| 930 | .max = 32767, | ||
| 931 | .step = 1, | ||
| 932 | }; | ||
| 933 | |||
| 934 | static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = { | ||
| 935 | .ops = &go7007_ctrl_ops, | ||
| 936 | .id = V4L2_CID_MB_THRESHOLD0, | ||
| 937 | .name = "MB Threshold Region 0", | ||
| 938 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 939 | .def = 200, | ||
| 940 | .max = 32767, | ||
| 941 | .step = 1, | ||
| 942 | }; | ||
| 943 | |||
| 944 | static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = { | ||
| 945 | .ops = &go7007_ctrl_ops, | ||
| 946 | .id = V4L2_CID_PIXEL_THRESHOLD1, | ||
| 947 | .name = "Pixel Threshold Region 1", | ||
| 948 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 949 | .def = 20, | ||
| 950 | .max = 32767, | ||
| 951 | .step = 1, | ||
| 952 | }; | ||
| 953 | |||
| 954 | static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = { | ||
| 955 | .ops = &go7007_ctrl_ops, | ||
| 956 | .id = V4L2_CID_MOTION_THRESHOLD1, | ||
| 957 | .name = "Motion Threshold Region 1", | ||
| 958 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 959 | .def = 80, | ||
| 960 | .max = 32767, | ||
| 961 | .step = 1, | ||
| 962 | }; | ||
| 963 | |||
| 964 | static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = { | ||
| 965 | .ops = &go7007_ctrl_ops, | ||
| 966 | .id = V4L2_CID_MB_THRESHOLD1, | ||
| 967 | .name = "MB Threshold Region 1", | ||
| 968 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 969 | .def = 200, | ||
| 970 | .max = 32767, | ||
| 971 | .step = 1, | ||
| 972 | }; | ||
| 973 | |||
| 974 | static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = { | ||
| 975 | .ops = &go7007_ctrl_ops, | ||
| 976 | .id = V4L2_CID_PIXEL_THRESHOLD2, | ||
| 977 | .name = "Pixel Threshold Region 2", | ||
| 978 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 979 | .def = 20, | ||
| 980 | .max = 32767, | ||
| 981 | .step = 1, | ||
| 982 | }; | ||
| 983 | |||
| 984 | static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = { | ||
| 985 | .ops = &go7007_ctrl_ops, | ||
| 986 | .id = V4L2_CID_MOTION_THRESHOLD2, | ||
| 987 | .name = "Motion Threshold Region 2", | ||
| 988 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 989 | .def = 80, | ||
| 990 | .max = 32767, | ||
| 991 | .step = 1, | ||
| 992 | }; | ||
| 993 | |||
| 994 | static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = { | ||
| 995 | .ops = &go7007_ctrl_ops, | ||
| 996 | .id = V4L2_CID_MB_THRESHOLD2, | ||
| 997 | .name = "MB Threshold Region 2", | ||
| 998 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 999 | .def = 200, | ||
| 1000 | .max = 32767, | ||
| 1001 | .step = 1, | ||
| 1002 | }; | ||
| 1003 | |||
| 1004 | static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = { | ||
| 1005 | .ops = &go7007_ctrl_ops, | ||
| 1006 | .id = V4L2_CID_PIXEL_THRESHOLD3, | ||
| 1007 | .name = "Pixel Threshold Region 3", | ||
| 1008 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1009 | .def = 20, | ||
| 1010 | .max = 32767, | ||
| 1011 | .step = 1, | ||
| 1012 | }; | ||
| 1013 | |||
| 1014 | static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = { | ||
| 1015 | .ops = &go7007_ctrl_ops, | ||
| 1016 | .id = V4L2_CID_MOTION_THRESHOLD3, | ||
| 1017 | .name = "Motion Threshold Region 3", | ||
| 1018 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1019 | .def = 80, | ||
| 1020 | .max = 32767, | ||
| 1021 | .step = 1, | ||
| 1022 | }; | ||
| 1023 | |||
| 1024 | static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = { | ||
| 1025 | .ops = &go7007_ctrl_ops, | ||
| 1026 | .id = V4L2_CID_MB_THRESHOLD3, | ||
| 1027 | .name = "MB Threshold Region 3", | ||
| 1028 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
| 1029 | .def = 200, | ||
| 1030 | .max = 32767, | ||
| 1031 | .step = 1, | ||
| 1032 | }; | ||
| 1033 | |||
| 1034 | static const struct v4l2_ctrl_config go7007_mb_regions_ctrl = { | ||
| 1035 | .ops = &go7007_ctrl_ops, | ||
| 1036 | .id = V4L2_CID_DETECT_MD_REGION_GRID, | ||
| 1037 | .dims = { 576 / 16, 720 / 16 }, | ||
| 1038 | .max = 3, | ||
| 1039 | .step = 1, | ||
| 1040 | }; | ||
| 1041 | |||
| 1042 | int go7007_v4l2_ctrl_init(struct go7007 *go) | ||
| 1043 | { | ||
| 1044 | struct v4l2_ctrl_handler *hdl = &go->hdl; | ||
| 1045 | struct v4l2_ctrl *ctrl; | ||
| 1046 | |||
| 1047 | v4l2_ctrl_handler_init(hdl, 22); | ||
| 1048 | go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1049 | V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15); | ||
| 1050 | go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1051 | V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1); | ||
| 1052 | go->mpeg_video_bitrate = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1053 | V4L2_CID_MPEG_VIDEO_BITRATE, | ||
| 1054 | 64000, 10000000, 1, 9800000); | ||
| 1055 | go->mpeg_video_b_frames = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1056 | V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 2, 2, 0); | ||
| 1057 | go->mpeg_video_rep_seqheader = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1058 | V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 0, 1, 1, 1); | ||
| 1059 | |||
| 1060 | go->mpeg_video_aspect_ratio = v4l2_ctrl_new_std_menu(hdl, NULL, | ||
| 1061 | V4L2_CID_MPEG_VIDEO_ASPECT, | ||
| 1062 | V4L2_MPEG_VIDEO_ASPECT_16x9, 0, | ||
| 1063 | V4L2_MPEG_VIDEO_ASPECT_1x1); | ||
| 1064 | ctrl = v4l2_ctrl_new_std(hdl, NULL, | ||
| 1065 | V4L2_CID_JPEG_ACTIVE_MARKER, 0, | ||
| 1066 | V4L2_JPEG_ACTIVE_MARKER_DQT | | ||
| 1067 | V4L2_JPEG_ACTIVE_MARKER_DHT, 0, | ||
| 1068 | V4L2_JPEG_ACTIVE_MARKER_DQT | | ||
| 1069 | V4L2_JPEG_ACTIVE_MARKER_DHT); | ||
| 1070 | if (ctrl) | ||
| 1071 | ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 1072 | v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold0_ctrl, NULL); | ||
| 1073 | v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold0_ctrl, NULL); | ||
| 1074 | v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold0_ctrl, NULL); | ||
| 1075 | v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold1_ctrl, NULL); | ||
| 1076 | v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold1_ctrl, NULL); | ||
| 1077 | v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold1_ctrl, NULL); | ||
| 1078 | v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold2_ctrl, NULL); | ||
| 1079 | v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold2_ctrl, NULL); | ||
| 1080 | v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold2_ctrl, NULL); | ||
| 1081 | v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold3_ctrl, NULL); | ||
| 1082 | v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold3_ctrl, NULL); | ||
| 1083 | v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold3_ctrl, NULL); | ||
| 1084 | v4l2_ctrl_new_custom(hdl, &go7007_mb_regions_ctrl, NULL); | ||
| 1085 | go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL, | ||
| 1086 | V4L2_CID_DETECT_MD_MODE, | ||
| 1087 | V4L2_DETECT_MD_MODE_REGION_GRID, | ||
| 1088 | 1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID, | ||
| 1089 | V4L2_DETECT_MD_MODE_DISABLED); | ||
| 1090 | if (hdl->error) { | ||
| 1091 | int rv = hdl->error; | ||
| 1092 | |||
| 1093 | v4l2_err(&go->v4l2_dev, "Could not register controls\n"); | ||
| 1094 | return rv; | ||
| 1095 | } | ||
| 1096 | go->v4l2_dev.ctrl_handler = hdl; | ||
| 1097 | return 0; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | int go7007_v4l2_init(struct go7007 *go) | ||
| 1101 | { | ||
| 1102 | struct video_device *vdev = &go->vdev; | ||
| 1103 | int rv; | ||
| 1104 | |||
| 1105 | mutex_init(&go->serialize_lock); | ||
| 1106 | mutex_init(&go->queue_lock); | ||
| 1107 | |||
| 1108 | INIT_LIST_HEAD(&go->vidq_active); | ||
| 1109 | go->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 1110 | go->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; | ||
| 1111 | go->vidq.ops = &go7007_video_qops; | ||
| 1112 | go->vidq.mem_ops = &vb2_vmalloc_memops; | ||
| 1113 | go->vidq.drv_priv = go; | ||
| 1114 | go->vidq.buf_struct_size = sizeof(struct go7007_buffer); | ||
| 1115 | go->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
| 1116 | go->vidq.lock = &go->queue_lock; | ||
| 1117 | rv = vb2_queue_init(&go->vidq); | ||
| 1118 | if (rv) | ||
| 1119 | return rv; | ||
| 1120 | *vdev = go7007_template; | ||
| 1121 | vdev->lock = &go->serialize_lock; | ||
| 1122 | vdev->queue = &go->vidq; | ||
| 1123 | video_set_drvdata(vdev, go); | ||
| 1124 | vdev->v4l2_dev = &go->v4l2_dev; | ||
| 1125 | if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd)) | ||
| 1126 | v4l2_disable_ioctl(vdev, VIDIOC_QUERYSTD); | ||
| 1127 | if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER)) { | ||
| 1128 | v4l2_disable_ioctl(vdev, VIDIOC_S_FREQUENCY); | ||
| 1129 | v4l2_disable_ioctl(vdev, VIDIOC_G_FREQUENCY); | ||
| 1130 | v4l2_disable_ioctl(vdev, VIDIOC_S_TUNER); | ||
| 1131 | v4l2_disable_ioctl(vdev, VIDIOC_G_TUNER); | ||
| 1132 | } else { | ||
| 1133 | struct v4l2_frequency f = { | ||
| 1134 | .type = V4L2_TUNER_ANALOG_TV, | ||
| 1135 | .frequency = 980, | ||
| 1136 | }; | ||
| 1137 | |||
| 1138 | call_all(&go->v4l2_dev, tuner, s_frequency, &f); | ||
| 1139 | } | ||
| 1140 | if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV)) { | ||
| 1141 | v4l2_disable_ioctl(vdev, VIDIOC_G_STD); | ||
| 1142 | v4l2_disable_ioctl(vdev, VIDIOC_S_STD); | ||
| 1143 | vdev->tvnorms = 0; | ||
| 1144 | } | ||
| 1145 | if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) | ||
| 1146 | v4l2_disable_ioctl(vdev, VIDIOC_ENUM_FRAMESIZES); | ||
| 1147 | if (go->board_info->num_aud_inputs == 0) { | ||
| 1148 | v4l2_disable_ioctl(vdev, VIDIOC_G_AUDIO); | ||
| 1149 | v4l2_disable_ioctl(vdev, VIDIOC_S_AUDIO); | ||
| 1150 | v4l2_disable_ioctl(vdev, VIDIOC_ENUMAUDIO); | ||
| 1151 | } | ||
| 1152 | /* Setup correct crystal frequency on this board */ | ||
| 1153 | if (go->board_info->sensor_flags & GO7007_SENSOR_SAA7115) | ||
| 1154 | v4l2_subdev_call(go->sd_video, video, s_crystal_freq, | ||
| 1155 | SAA7115_FREQ_24_576_MHZ, | ||
| 1156 | SAA7115_FREQ_FL_APLL | SAA7115_FREQ_FL_UCGC | | ||
| 1157 | SAA7115_FREQ_FL_DOUBLE_ASCLK); | ||
| 1158 | go7007_s_input(go); | ||
| 1159 | if (go->board_info->sensor_flags & GO7007_SENSOR_TV) | ||
| 1160 | go7007_s_std(go); | ||
| 1161 | rv = video_register_device(vdev, VFL_TYPE_GRABBER, -1); | ||
| 1162 | if (rv < 0) | ||
| 1163 | return rv; | ||
| 1164 | dev_info(go->dev, "registered device %s [v4l2]\n", | ||
| 1165 | video_device_node_name(vdev)); | ||
| 1166 | |||
| 1167 | return 0; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | void go7007_v4l2_remove(struct go7007 *go) | ||
| 1171 | { | ||
| 1172 | v4l2_ctrl_handler_free(&go->hdl); | ||
| 1173 | } | ||
diff --git a/drivers/media/usb/go7007/s2250-board.c b/drivers/media/usb/go7007/s2250-board.c new file mode 100644 index 000000000000..bb846680bcd4 --- /dev/null +++ b/drivers/media/usb/go7007/s2250-board.c | |||
| @@ -0,0 +1,628 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2008 Sensoray Company Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/usb.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/videodev2.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | #include <media/v4l2-device.h> | ||
| 20 | #include <media/v4l2-common.h> | ||
| 21 | #include <media/v4l2-subdev.h> | ||
| 22 | #include "go7007-priv.h" | ||
| 23 | |||
| 24 | MODULE_DESCRIPTION("Sensoray 2250/2251 i2c v4l2 subdev driver"); | ||
| 25 | MODULE_LICENSE("GPL v2"); | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Note: this board has two i2c devices: a vpx3226f and a tlv320aic23b. | ||
| 29 | * Due to the unusual way these are accessed on this device we do not | ||
| 30 | * reuse the i2c drivers, but instead they are implemented in this | ||
| 31 | * driver. It would be nice to improve on this, though. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define TLV320_ADDRESS 0x34 | ||
| 35 | #define VPX322_ADDR_ANALOGCONTROL1 0x02 | ||
| 36 | #define VPX322_ADDR_BRIGHTNESS0 0x0127 | ||
| 37 | #define VPX322_ADDR_BRIGHTNESS1 0x0131 | ||
| 38 | #define VPX322_ADDR_CONTRAST0 0x0128 | ||
| 39 | #define VPX322_ADDR_CONTRAST1 0x0132 | ||
| 40 | #define VPX322_ADDR_HUE 0x00dc | ||
| 41 | #define VPX322_ADDR_SAT 0x0030 | ||
| 42 | |||
| 43 | struct go7007_usb_board { | ||
| 44 | unsigned int flags; | ||
| 45 | struct go7007_board_info main_info; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct go7007_usb { | ||
| 49 | struct go7007_usb_board *board; | ||
| 50 | struct mutex i2c_lock; | ||
| 51 | struct usb_device *usbdev; | ||
| 52 | struct urb *video_urbs[8]; | ||
| 53 | struct urb *audio_urbs[8]; | ||
| 54 | struct urb *intr_urb; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static unsigned char aud_regs[] = { | ||
| 58 | 0x1e, 0x00, | ||
| 59 | 0x00, 0x17, | ||
| 60 | 0x02, 0x17, | ||
| 61 | 0x04, 0xf9, | ||
| 62 | 0x06, 0xf9, | ||
| 63 | 0x08, 0x02, | ||
| 64 | 0x0a, 0x00, | ||
| 65 | 0x0c, 0x00, | ||
| 66 | 0x0a, 0x00, | ||
| 67 | 0x0c, 0x00, | ||
| 68 | 0x0e, 0x02, | ||
| 69 | 0x10, 0x00, | ||
| 70 | 0x12, 0x01, | ||
| 71 | 0x00, 0x00, | ||
| 72 | }; | ||
| 73 | |||
| 74 | |||
| 75 | static unsigned char vid_regs[] = { | ||
| 76 | 0xF2, 0x0f, | ||
| 77 | 0xAA, 0x00, | ||
| 78 | 0xF8, 0xff, | ||
| 79 | 0x00, 0x00, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static u16 vid_regs_fp[] = { | ||
| 83 | 0x028, 0x067, | ||
| 84 | 0x120, 0x016, | ||
| 85 | 0x121, 0xcF2, | ||
| 86 | 0x122, 0x0F2, | ||
| 87 | 0x123, 0x00c, | ||
| 88 | 0x124, 0x2d0, | ||
| 89 | 0x125, 0x2e0, | ||
| 90 | 0x126, 0x004, | ||
| 91 | 0x128, 0x1E0, | ||
| 92 | 0x12A, 0x016, | ||
| 93 | 0x12B, 0x0F2, | ||
| 94 | 0x12C, 0x0F2, | ||
| 95 | 0x12D, 0x00c, | ||
| 96 | 0x12E, 0x2d0, | ||
| 97 | 0x12F, 0x2e0, | ||
| 98 | 0x130, 0x004, | ||
| 99 | 0x132, 0x1E0, | ||
| 100 | 0x140, 0x060, | ||
| 101 | 0x153, 0x00C, | ||
| 102 | 0x154, 0x200, | ||
| 103 | 0x150, 0x801, | ||
| 104 | 0x000, 0x000 | ||
| 105 | }; | ||
| 106 | |||
| 107 | /* PAL specific values */ | ||
| 108 | static u16 vid_regs_fp_pal[] = { | ||
| 109 | 0x120, 0x017, | ||
| 110 | 0x121, 0xd22, | ||
| 111 | 0x122, 0x122, | ||
| 112 | 0x12A, 0x017, | ||
| 113 | 0x12B, 0x122, | ||
| 114 | 0x12C, 0x122, | ||
| 115 | 0x140, 0x060, | ||
| 116 | 0x000, 0x000, | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct s2250 { | ||
| 120 | struct v4l2_subdev sd; | ||
| 121 | struct v4l2_ctrl_handler hdl; | ||
| 122 | v4l2_std_id std; | ||
| 123 | int input; | ||
| 124 | int brightness; | ||
| 125 | int contrast; | ||
| 126 | int saturation; | ||
| 127 | int hue; | ||
| 128 | int reg12b_val; | ||
| 129 | int audio_input; | ||
| 130 | struct i2c_client *audio; | ||
| 131 | }; | ||
| 132 | |||
| 133 | static inline struct s2250 *to_state(struct v4l2_subdev *sd) | ||
| 134 | { | ||
| 135 | return container_of(sd, struct s2250, sd); | ||
| 136 | } | ||
| 137 | |||
| 138 | /* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ | ||
| 139 | static int go7007_usb_vendor_request(struct go7007 *go, u16 request, | ||
| 140 | u16 value, u16 index, void *transfer_buffer, int length, int in) | ||
| 141 | { | ||
| 142 | struct go7007_usb *usb = go->hpi_context; | ||
| 143 | int timeout = 5000; | ||
| 144 | |||
| 145 | if (in) { | ||
| 146 | return usb_control_msg(usb->usbdev, | ||
| 147 | usb_rcvctrlpipe(usb->usbdev, 0), request, | ||
| 148 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
| 149 | value, index, transfer_buffer, length, timeout); | ||
| 150 | } else { | ||
| 151 | return usb_control_msg(usb->usbdev, | ||
| 152 | usb_sndctrlpipe(usb->usbdev, 0), request, | ||
| 153 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 154 | value, index, transfer_buffer, length, timeout); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | /* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/ | ||
| 158 | |||
| 159 | static int write_reg(struct i2c_client *client, u8 reg, u8 value) | ||
| 160 | { | ||
| 161 | struct go7007 *go = i2c_get_adapdata(client->adapter); | ||
| 162 | struct go7007_usb *usb; | ||
| 163 | int rc; | ||
| 164 | int dev_addr = client->addr << 1; /* firmware wants 8-bit address */ | ||
| 165 | u8 *buf; | ||
| 166 | |||
| 167 | if (go == NULL) | ||
| 168 | return -ENODEV; | ||
| 169 | |||
| 170 | if (go->status == STATUS_SHUTDOWN) | ||
| 171 | return -EBUSY; | ||
| 172 | |||
| 173 | buf = kzalloc(16, GFP_KERNEL); | ||
| 174 | if (buf == NULL) | ||
| 175 | return -ENOMEM; | ||
| 176 | |||
| 177 | usb = go->hpi_context; | ||
| 178 | if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { | ||
| 179 | dev_info(&client->dev, "i2c lock failed\n"); | ||
| 180 | kfree(buf); | ||
| 181 | return -EINTR; | ||
| 182 | } | ||
| 183 | rc = go7007_usb_vendor_request(go, 0x55, dev_addr, | ||
| 184 | (reg<<8 | value), | ||
| 185 | buf, | ||
| 186 | 16, 1); | ||
| 187 | |||
| 188 | mutex_unlock(&usb->i2c_lock); | ||
| 189 | kfree(buf); | ||
| 190 | return rc; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val) | ||
| 194 | { | ||
| 195 | struct go7007 *go = i2c_get_adapdata(client->adapter); | ||
| 196 | struct go7007_usb *usb; | ||
| 197 | int rc; | ||
| 198 | u8 *buf; | ||
| 199 | struct s2250 *dec = i2c_get_clientdata(client); | ||
| 200 | |||
| 201 | if (go == NULL) | ||
| 202 | return -ENODEV; | ||
| 203 | |||
| 204 | if (go->status == STATUS_SHUTDOWN) | ||
| 205 | return -EBUSY; | ||
| 206 | |||
| 207 | buf = kzalloc(16, GFP_KERNEL); | ||
| 208 | |||
| 209 | if (buf == NULL) | ||
| 210 | return -ENOMEM; | ||
| 211 | |||
| 212 | |||
| 213 | |||
| 214 | memset(buf, 0xcd, 6); | ||
| 215 | |||
| 216 | usb = go->hpi_context; | ||
| 217 | if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { | ||
| 218 | dev_info(&client->dev, "i2c lock failed\n"); | ||
| 219 | kfree(buf); | ||
| 220 | return -EINTR; | ||
| 221 | } | ||
| 222 | rc = go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1); | ||
| 223 | mutex_unlock(&usb->i2c_lock); | ||
| 224 | if (rc < 0) { | ||
| 225 | kfree(buf); | ||
| 226 | return rc; | ||
| 227 | } | ||
| 228 | |||
| 229 | if (buf[0] == 0) { | ||
| 230 | unsigned int subaddr, val_read; | ||
| 231 | |||
| 232 | subaddr = (buf[4] << 8) + buf[5]; | ||
| 233 | val_read = (buf[2] << 8) + buf[3]; | ||
| 234 | kfree(buf); | ||
| 235 | if (val_read != val) { | ||
| 236 | dev_info(&client->dev, "invalid fp write %x %x\n", | ||
| 237 | val_read, val); | ||
| 238 | return -EFAULT; | ||
| 239 | } | ||
| 240 | if (subaddr != addr) { | ||
| 241 | dev_info(&client->dev, "invalid fp write addr %x %x\n", | ||
| 242 | subaddr, addr); | ||
| 243 | return -EFAULT; | ||
| 244 | } | ||
| 245 | } else { | ||
| 246 | kfree(buf); | ||
| 247 | return -EFAULT; | ||
| 248 | } | ||
| 249 | |||
| 250 | /* save last 12b value */ | ||
| 251 | if (addr == 0x12b) | ||
| 252 | dec->reg12b_val = val; | ||
| 253 | |||
| 254 | return 0; | ||
| 255 | } | ||
| 256 | |||
| 257 | static int read_reg_fp(struct i2c_client *client, u16 addr, u16 *val) | ||
| 258 | { | ||
| 259 | struct go7007 *go = i2c_get_adapdata(client->adapter); | ||
| 260 | struct go7007_usb *usb; | ||
| 261 | int rc; | ||
| 262 | u8 *buf; | ||
| 263 | |||
| 264 | if (go == NULL) | ||
| 265 | return -ENODEV; | ||
| 266 | |||
| 267 | if (go->status == STATUS_SHUTDOWN) | ||
| 268 | return -EBUSY; | ||
| 269 | |||
| 270 | buf = kzalloc(16, GFP_KERNEL); | ||
| 271 | |||
| 272 | if (buf == NULL) | ||
| 273 | return -ENOMEM; | ||
| 274 | |||
| 275 | |||
| 276 | |||
| 277 | memset(buf, 0xcd, 6); | ||
| 278 | usb = go->hpi_context; | ||
| 279 | if (mutex_lock_interruptible(&usb->i2c_lock) != 0) { | ||
| 280 | dev_info(&client->dev, "i2c lock failed\n"); | ||
| 281 | kfree(buf); | ||
| 282 | return -EINTR; | ||
| 283 | } | ||
| 284 | rc = go7007_usb_vendor_request(go, 0x58, addr, 0, buf, 16, 1); | ||
| 285 | mutex_unlock(&usb->i2c_lock); | ||
| 286 | if (rc < 0) { | ||
| 287 | kfree(buf); | ||
| 288 | return rc; | ||
| 289 | } | ||
| 290 | |||
| 291 | *val = (buf[0] << 8) | buf[1]; | ||
| 292 | kfree(buf); | ||
| 293 | |||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | |||
| 298 | static int write_regs(struct i2c_client *client, u8 *regs) | ||
| 299 | { | ||
| 300 | int i; | ||
| 301 | |||
| 302 | for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) { | ||
| 303 | if (write_reg(client, regs[i], regs[i+1]) < 0) { | ||
| 304 | dev_info(&client->dev, "failed\n"); | ||
| 305 | return -1; | ||
| 306 | } | ||
| 307 | } | ||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int write_regs_fp(struct i2c_client *client, u16 *regs) | ||
| 312 | { | ||
| 313 | int i; | ||
| 314 | |||
| 315 | for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) { | ||
| 316 | if (write_reg_fp(client, regs[i], regs[i+1]) < 0) { | ||
| 317 | dev_info(&client->dev, "failed fp\n"); | ||
| 318 | return -1; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | |||
| 325 | /* ------------------------------------------------------------------------- */ | ||
| 326 | |||
| 327 | static int s2250_s_video_routing(struct v4l2_subdev *sd, u32 input, u32 output, | ||
| 328 | u32 config) | ||
| 329 | { | ||
| 330 | struct s2250 *state = to_state(sd); | ||
| 331 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 332 | int vidsys; | ||
| 333 | |||
| 334 | vidsys = (state->std == V4L2_STD_NTSC) ? 0x01 : 0x00; | ||
| 335 | if (input == 0) { | ||
| 336 | /* composite */ | ||
| 337 | write_reg_fp(client, 0x20, 0x020 | vidsys); | ||
| 338 | write_reg_fp(client, 0x21, 0x662); | ||
| 339 | write_reg_fp(client, 0x140, 0x060); | ||
| 340 | } else if (input == 1) { | ||
| 341 | /* S-Video */ | ||
| 342 | write_reg_fp(client, 0x20, 0x040 | vidsys); | ||
| 343 | write_reg_fp(client, 0x21, 0x666); | ||
| 344 | write_reg_fp(client, 0x140, 0x060); | ||
| 345 | } else { | ||
| 346 | return -EINVAL; | ||
| 347 | } | ||
| 348 | state->input = input; | ||
| 349 | return 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | static int s2250_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) | ||
| 353 | { | ||
| 354 | struct s2250 *state = to_state(sd); | ||
| 355 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 356 | u16 vidsource; | ||
| 357 | |||
| 358 | vidsource = (state->input == 1) ? 0x040 : 0x020; | ||
| 359 | if (norm & V4L2_STD_625_50) { | ||
| 360 | write_regs_fp(client, vid_regs_fp); | ||
| 361 | write_regs_fp(client, vid_regs_fp_pal); | ||
| 362 | write_reg_fp(client, 0x20, vidsource); | ||
| 363 | } else { | ||
| 364 | write_regs_fp(client, vid_regs_fp); | ||
| 365 | write_reg_fp(client, 0x20, vidsource | 1); | ||
| 366 | } | ||
| 367 | state->std = norm; | ||
| 368 | return 0; | ||
| 369 | } | ||
| 370 | |||
| 371 | static int s2250_s_ctrl(struct v4l2_ctrl *ctrl) | ||
| 372 | { | ||
| 373 | struct s2250 *state = container_of(ctrl->handler, struct s2250, hdl); | ||
| 374 | struct i2c_client *client = v4l2_get_subdevdata(&state->sd); | ||
| 375 | u16 oldvalue; | ||
| 376 | |||
| 377 | switch (ctrl->id) { | ||
| 378 | case V4L2_CID_BRIGHTNESS: | ||
| 379 | read_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, &oldvalue); | ||
| 380 | write_reg_fp(client, VPX322_ADDR_BRIGHTNESS0, | ||
| 381 | ctrl->val | (oldvalue & ~0xff)); | ||
| 382 | read_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, &oldvalue); | ||
| 383 | write_reg_fp(client, VPX322_ADDR_BRIGHTNESS1, | ||
| 384 | ctrl->val | (oldvalue & ~0xff)); | ||
| 385 | write_reg_fp(client, 0x140, 0x60); | ||
| 386 | break; | ||
| 387 | case V4L2_CID_CONTRAST: | ||
| 388 | read_reg_fp(client, VPX322_ADDR_CONTRAST0, &oldvalue); | ||
| 389 | write_reg_fp(client, VPX322_ADDR_CONTRAST0, | ||
| 390 | ctrl->val | (oldvalue & ~0x3f)); | ||
| 391 | read_reg_fp(client, VPX322_ADDR_CONTRAST1, &oldvalue); | ||
| 392 | write_reg_fp(client, VPX322_ADDR_CONTRAST1, | ||
| 393 | ctrl->val | (oldvalue & ~0x3f)); | ||
| 394 | write_reg_fp(client, 0x140, 0x60); | ||
| 395 | break; | ||
| 396 | case V4L2_CID_SATURATION: | ||
| 397 | write_reg_fp(client, VPX322_ADDR_SAT, ctrl->val); | ||
| 398 | break; | ||
| 399 | case V4L2_CID_HUE: | ||
| 400 | write_reg_fp(client, VPX322_ADDR_HUE, ctrl->val); | ||
| 401 | break; | ||
| 402 | default: | ||
| 403 | return -EINVAL; | ||
| 404 | } | ||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static int s2250_s_mbus_fmt(struct v4l2_subdev *sd, | ||
| 409 | struct v4l2_mbus_framefmt *fmt) | ||
| 410 | { | ||
| 411 | struct s2250 *state = to_state(sd); | ||
| 412 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
| 413 | |||
| 414 | if (fmt->height < 640) { | ||
| 415 | write_reg_fp(client, 0x12b, state->reg12b_val | 0x400); | ||
| 416 | write_reg_fp(client, 0x140, 0x060); | ||
| 417 | } else { | ||
| 418 | write_reg_fp(client, 0x12b, state->reg12b_val & ~0x400); | ||
| 419 | write_reg_fp(client, 0x140, 0x060); | ||
| 420 | } | ||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | static int s2250_s_audio_routing(struct v4l2_subdev *sd, u32 input, u32 output, | ||
| 425 | u32 config) | ||
| 426 | { | ||
| 427 | struct s2250 *state = to_state(sd); | ||
| 428 | |||
| 429 | switch (input) { | ||
| 430 | case 0: | ||
| 431 | write_reg(state->audio, 0x08, 0x02); /* Line In */ | ||
| 432 | break; | ||
| 433 | case 1: | ||
| 434 | write_reg(state->audio, 0x08, 0x04); /* Mic */ | ||
| 435 | break; | ||
| 436 | case 2: | ||
| 437 | write_reg(state->audio, 0x08, 0x05); /* Mic Boost */ | ||
| 438 | break; | ||
| 439 | default: | ||
| 440 | return -EINVAL; | ||
| 441 | } | ||
| 442 | state->audio_input = input; | ||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | |||
| 447 | static int s2250_log_status(struct v4l2_subdev *sd) | ||
| 448 | { | ||
| 449 | struct s2250 *state = to_state(sd); | ||
| 450 | |||
| 451 | v4l2_info(sd, "Standard: %s\n", state->std == V4L2_STD_NTSC ? "NTSC" : | ||
| 452 | state->std == V4L2_STD_PAL ? "PAL" : | ||
| 453 | state->std == V4L2_STD_SECAM ? "SECAM" : | ||
| 454 | "unknown"); | ||
| 455 | v4l2_info(sd, "Input: %s\n", state->input == 0 ? "Composite" : | ||
| 456 | state->input == 1 ? "S-video" : | ||
| 457 | "error"); | ||
| 458 | v4l2_info(sd, "Audio input: %s\n", state->audio_input == 0 ? "Line In" : | ||
| 459 | state->audio_input == 1 ? "Mic" : | ||
| 460 | state->audio_input == 2 ? "Mic Boost" : | ||
| 461 | "error"); | ||
| 462 | return v4l2_ctrl_subdev_log_status(sd); | ||
| 463 | } | ||
| 464 | |||
| 465 | /* --------------------------------------------------------------------------*/ | ||
| 466 | |||
| 467 | static const struct v4l2_ctrl_ops s2250_ctrl_ops = { | ||
| 468 | .s_ctrl = s2250_s_ctrl, | ||
| 469 | }; | ||
| 470 | |||
| 471 | static const struct v4l2_subdev_core_ops s2250_core_ops = { | ||
| 472 | .log_status = s2250_log_status, | ||
| 473 | }; | ||
| 474 | |||
| 475 | static const struct v4l2_subdev_audio_ops s2250_audio_ops = { | ||
| 476 | .s_routing = s2250_s_audio_routing, | ||
| 477 | }; | ||
| 478 | |||
| 479 | static const struct v4l2_subdev_video_ops s2250_video_ops = { | ||
| 480 | .s_std = s2250_s_std, | ||
| 481 | .s_routing = s2250_s_video_routing, | ||
| 482 | .s_mbus_fmt = s2250_s_mbus_fmt, | ||
| 483 | }; | ||
| 484 | |||
| 485 | static const struct v4l2_subdev_ops s2250_ops = { | ||
| 486 | .core = &s2250_core_ops, | ||
| 487 | .audio = &s2250_audio_ops, | ||
| 488 | .video = &s2250_video_ops, | ||
| 489 | }; | ||
| 490 | |||
| 491 | /* --------------------------------------------------------------------------*/ | ||
| 492 | |||
| 493 | static int s2250_probe(struct i2c_client *client, | ||
| 494 | const struct i2c_device_id *id) | ||
| 495 | { | ||
| 496 | struct i2c_client *audio; | ||
| 497 | struct i2c_adapter *adapter = client->adapter; | ||
| 498 | struct s2250 *state; | ||
| 499 | struct v4l2_subdev *sd; | ||
| 500 | u8 *data; | ||
| 501 | struct go7007 *go = i2c_get_adapdata(adapter); | ||
| 502 | struct go7007_usb *usb = go->hpi_context; | ||
| 503 | |||
| 504 | audio = i2c_new_dummy(adapter, TLV320_ADDRESS >> 1); | ||
| 505 | if (audio == NULL) | ||
| 506 | return -ENOMEM; | ||
| 507 | |||
| 508 | state = kzalloc(sizeof(struct s2250), GFP_KERNEL); | ||
| 509 | if (state == NULL) { | ||
| 510 | i2c_unregister_device(audio); | ||
| 511 | return -ENOMEM; | ||
| 512 | } | ||
| 513 | |||
| 514 | sd = &state->sd; | ||
| 515 | v4l2_i2c_subdev_init(sd, client, &s2250_ops); | ||
| 516 | |||
| 517 | v4l2_info(sd, "initializing %s at address 0x%x on %s\n", | ||
| 518 | "Sensoray 2250/2251", client->addr, client->adapter->name); | ||
| 519 | |||
| 520 | v4l2_ctrl_handler_init(&state->hdl, 4); | ||
| 521 | v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, | ||
| 522 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); | ||
| 523 | v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, | ||
| 524 | V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x32); | ||
| 525 | v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, | ||
| 526 | V4L2_CID_SATURATION, 0, 4094, 1, 2070); | ||
| 527 | v4l2_ctrl_new_std(&state->hdl, &s2250_ctrl_ops, | ||
| 528 | V4L2_CID_HUE, -512, 511, 1, 0); | ||
| 529 | sd->ctrl_handler = &state->hdl; | ||
| 530 | if (state->hdl.error) { | ||
| 531 | int err = state->hdl.error; | ||
| 532 | |||
| 533 | v4l2_ctrl_handler_free(&state->hdl); | ||
| 534 | kfree(state); | ||
| 535 | return err; | ||
| 536 | } | ||
| 537 | |||
| 538 | state->std = V4L2_STD_NTSC; | ||
| 539 | state->brightness = 50; | ||
| 540 | state->contrast = 50; | ||
| 541 | state->saturation = 50; | ||
| 542 | state->hue = 0; | ||
| 543 | state->audio = audio; | ||
| 544 | |||
| 545 | /* initialize the audio */ | ||
| 546 | if (write_regs(audio, aud_regs) < 0) { | ||
| 547 | dev_err(&client->dev, "error initializing audio\n"); | ||
| 548 | goto fail; | ||
| 549 | } | ||
| 550 | |||
| 551 | if (write_regs(client, vid_regs) < 0) { | ||
| 552 | dev_err(&client->dev, "error initializing decoder\n"); | ||
| 553 | goto fail; | ||
| 554 | } | ||
| 555 | if (write_regs_fp(client, vid_regs_fp) < 0) { | ||
| 556 | dev_err(&client->dev, "error initializing decoder\n"); | ||
| 557 | goto fail; | ||
| 558 | } | ||
| 559 | /* set default channel */ | ||
| 560 | /* composite */ | ||
| 561 | write_reg_fp(client, 0x20, 0x020 | 1); | ||
| 562 | write_reg_fp(client, 0x21, 0x662); | ||
| 563 | write_reg_fp(client, 0x140, 0x060); | ||
| 564 | |||
| 565 | /* set default audio input */ | ||
| 566 | state->audio_input = 0; | ||
| 567 | write_reg(client, 0x08, 0x02); /* Line In */ | ||
| 568 | |||
| 569 | if (mutex_lock_interruptible(&usb->i2c_lock) == 0) { | ||
| 570 | data = kzalloc(16, GFP_KERNEL); | ||
| 571 | if (data != NULL) { | ||
| 572 | int rc = go7007_usb_vendor_request(go, 0x41, 0, 0, | ||
| 573 | data, 16, 1); | ||
| 574 | |||
| 575 | if (rc > 0) { | ||
| 576 | u8 mask; | ||
| 577 | |||
| 578 | data[0] = 0; | ||
| 579 | mask = 1<<5; | ||
| 580 | data[0] &= ~mask; | ||
| 581 | data[1] |= mask; | ||
| 582 | go7007_usb_vendor_request(go, 0x40, 0, | ||
| 583 | (data[1]<<8) | ||
| 584 | + data[1], | ||
| 585 | data, 16, 0); | ||
| 586 | } | ||
| 587 | kfree(data); | ||
| 588 | } | ||
| 589 | mutex_unlock(&usb->i2c_lock); | ||
| 590 | } | ||
| 591 | |||
| 592 | v4l2_info(sd, "initialized successfully\n"); | ||
| 593 | return 0; | ||
| 594 | |||
| 595 | fail: | ||
| 596 | i2c_unregister_device(audio); | ||
| 597 | v4l2_ctrl_handler_free(&state->hdl); | ||
| 598 | kfree(state); | ||
| 599 | return -EIO; | ||
| 600 | } | ||
| 601 | |||
| 602 | static int s2250_remove(struct i2c_client *client) | ||
| 603 | { | ||
| 604 | struct s2250 *state = to_state(i2c_get_clientdata(client)); | ||
| 605 | |||
| 606 | v4l2_device_unregister_subdev(&state->sd); | ||
| 607 | v4l2_ctrl_handler_free(&state->hdl); | ||
| 608 | kfree(state); | ||
| 609 | return 0; | ||
| 610 | } | ||
| 611 | |||
| 612 | static const struct i2c_device_id s2250_id[] = { | ||
| 613 | { "s2250", 0 }, | ||
| 614 | { } | ||
| 615 | }; | ||
| 616 | MODULE_DEVICE_TABLE(i2c, s2250_id); | ||
| 617 | |||
| 618 | static struct i2c_driver s2250_driver = { | ||
| 619 | .driver = { | ||
| 620 | .owner = THIS_MODULE, | ||
| 621 | .name = "s2250", | ||
| 622 | }, | ||
| 623 | .probe = s2250_probe, | ||
| 624 | .remove = s2250_remove, | ||
| 625 | .id_table = s2250_id, | ||
| 626 | }; | ||
| 627 | |||
| 628 | module_i2c_driver(s2250_driver); | ||
diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c new file mode 100644 index 000000000000..d22d7d574672 --- /dev/null +++ b/drivers/media/usb/go7007/snd-go7007.c | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005-2006 Micronas USA Inc. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License (Version 2) as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/moduleparam.h> | ||
| 17 | #include <linux/spinlock.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/vmalloc.h> | ||
| 21 | #include <linux/time.h> | ||
| 22 | #include <linux/mm.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <linux/mutex.h> | ||
| 25 | #include <linux/uaccess.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <sound/core.h> | ||
| 28 | #include <sound/pcm.h> | ||
| 29 | #include <sound/initval.h> | ||
| 30 | |||
| 31 | #include "go7007-priv.h" | ||
| 32 | |||
| 33 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
| 34 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
| 35 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
| 36 | |||
| 37 | module_param_array(index, int, NULL, 0444); | ||
| 38 | module_param_array(id, charp, NULL, 0444); | ||
| 39 | module_param_array(enable, bool, NULL, 0444); | ||
| 40 | MODULE_PARM_DESC(index, "Index value for the go7007 audio driver"); | ||
| 41 | MODULE_PARM_DESC(id, "ID string for the go7007 audio driver"); | ||
| 42 | MODULE_PARM_DESC(enable, "Enable for the go7007 audio driver"); | ||
| 43 | |||
| 44 | struct go7007_snd { | ||
| 45 | struct snd_card *card; | ||
| 46 | struct snd_pcm *pcm; | ||
| 47 | struct snd_pcm_substream *substream; | ||
| 48 | spinlock_t lock; | ||
| 49 | int w_idx; | ||
| 50 | int hw_ptr; | ||
| 51 | int avail; | ||
| 52 | int capturing; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static struct snd_pcm_hardware go7007_snd_capture_hw = { | ||
| 56 | .info = (SNDRV_PCM_INFO_MMAP | | ||
| 57 | SNDRV_PCM_INFO_INTERLEAVED | | ||
| 58 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
| 59 | SNDRV_PCM_INFO_MMAP_VALID), | ||
| 60 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 61 | .rates = SNDRV_PCM_RATE_48000, | ||
| 62 | .rate_min = 48000, | ||
| 63 | .rate_max = 48000, | ||
| 64 | .channels_min = 2, | ||
| 65 | .channels_max = 2, | ||
| 66 | .buffer_bytes_max = (128*1024), | ||
| 67 | .period_bytes_min = 4096, | ||
| 68 | .period_bytes_max = (128*1024), | ||
| 69 | .periods_min = 1, | ||
| 70 | .periods_max = 32, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static void parse_audio_stream_data(struct go7007 *go, u8 *buf, int length) | ||
| 74 | { | ||
| 75 | struct go7007_snd *gosnd = go->snd_context; | ||
| 76 | struct snd_pcm_runtime *runtime = gosnd->substream->runtime; | ||
| 77 | int frames = bytes_to_frames(runtime, length); | ||
| 78 | |||
| 79 | spin_lock(&gosnd->lock); | ||
| 80 | gosnd->hw_ptr += frames; | ||
| 81 | if (gosnd->hw_ptr >= runtime->buffer_size) | ||
| 82 | gosnd->hw_ptr -= runtime->buffer_size; | ||
| 83 | gosnd->avail += frames; | ||
| 84 | spin_unlock(&gosnd->lock); | ||
| 85 | if (gosnd->w_idx + length > runtime->dma_bytes) { | ||
| 86 | int cpy = runtime->dma_bytes - gosnd->w_idx; | ||
| 87 | |||
| 88 | memcpy(runtime->dma_area + gosnd->w_idx, buf, cpy); | ||
| 89 | length -= cpy; | ||
| 90 | buf += cpy; | ||
| 91 | gosnd->w_idx = 0; | ||
| 92 | } | ||
| 93 | memcpy(runtime->dma_area + gosnd->w_idx, buf, length); | ||
| 94 | gosnd->w_idx += length; | ||
| 95 | spin_lock(&gosnd->lock); | ||
| 96 | if (gosnd->avail < runtime->period_size) { | ||
| 97 | spin_unlock(&gosnd->lock); | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | gosnd->avail -= runtime->period_size; | ||
| 101 | spin_unlock(&gosnd->lock); | ||
| 102 | if (gosnd->capturing) | ||
| 103 | snd_pcm_period_elapsed(gosnd->substream); | ||
| 104 | } | ||
| 105 | |||
| 106 | static int go7007_snd_hw_params(struct snd_pcm_substream *substream, | ||
| 107 | struct snd_pcm_hw_params *hw_params) | ||
| 108 | { | ||
| 109 | struct go7007 *go = snd_pcm_substream_chip(substream); | ||
| 110 | unsigned int bytes; | ||
| 111 | |||
| 112 | bytes = params_buffer_bytes(hw_params); | ||
| 113 | if (substream->runtime->dma_bytes > 0) | ||
| 114 | vfree(substream->runtime->dma_area); | ||
| 115 | substream->runtime->dma_bytes = 0; | ||
| 116 | substream->runtime->dma_area = vmalloc(bytes); | ||
| 117 | if (substream->runtime->dma_area == NULL) | ||
| 118 | return -ENOMEM; | ||
| 119 | substream->runtime->dma_bytes = bytes; | ||
| 120 | go->audio_deliver = parse_audio_stream_data; | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | static int go7007_snd_hw_free(struct snd_pcm_substream *substream) | ||
| 125 | { | ||
| 126 | struct go7007 *go = snd_pcm_substream_chip(substream); | ||
| 127 | |||
| 128 | go->audio_deliver = NULL; | ||
| 129 | if (substream->runtime->dma_bytes > 0) | ||
| 130 | vfree(substream->runtime->dma_area); | ||
| 131 | substream->runtime->dma_bytes = 0; | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int go7007_snd_capture_open(struct snd_pcm_substream *substream) | ||
| 136 | { | ||
| 137 | struct go7007 *go = snd_pcm_substream_chip(substream); | ||
| 138 | struct go7007_snd *gosnd = go->snd_context; | ||
| 139 | unsigned long flags; | ||
| 140 | int r; | ||
| 141 | |||
| 142 | spin_lock_irqsave(&gosnd->lock, flags); | ||
| 143 | if (gosnd->substream == NULL) { | ||
| 144 | gosnd->substream = substream; | ||
| 145 | substream->runtime->hw = go7007_snd_capture_hw; | ||
| 146 | r = 0; | ||
| 147 | } else | ||
| 148 | r = -EBUSY; | ||
| 149 | spin_unlock_irqrestore(&gosnd->lock, flags); | ||
| 150 | return r; | ||
| 151 | } | ||
| 152 | |||
| 153 | static int go7007_snd_capture_close(struct snd_pcm_substream *substream) | ||
| 154 | { | ||
| 155 | struct go7007 *go = snd_pcm_substream_chip(substream); | ||
| 156 | struct go7007_snd *gosnd = go->snd_context; | ||
| 157 | |||
| 158 | gosnd->substream = NULL; | ||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | static int go7007_snd_pcm_prepare(struct snd_pcm_substream *substream) | ||
| 163 | { | ||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int go7007_snd_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
| 168 | { | ||
| 169 | struct go7007 *go = snd_pcm_substream_chip(substream); | ||
| 170 | struct go7007_snd *gosnd = go->snd_context; | ||
| 171 | |||
| 172 | switch (cmd) { | ||
| 173 | case SNDRV_PCM_TRIGGER_START: | ||
| 174 | /* Just set a flag to indicate we should signal ALSA when | ||
| 175 | * sound comes in */ | ||
| 176 | gosnd->capturing = 1; | ||
| 177 | return 0; | ||
| 178 | case SNDRV_PCM_TRIGGER_STOP: | ||
| 179 | gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; | ||
| 180 | gosnd->capturing = 0; | ||
| 181 | return 0; | ||
| 182 | default: | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | static snd_pcm_uframes_t go7007_snd_pcm_pointer(struct snd_pcm_substream *substream) | ||
| 188 | { | ||
| 189 | struct go7007 *go = snd_pcm_substream_chip(substream); | ||
| 190 | struct go7007_snd *gosnd = go->snd_context; | ||
| 191 | |||
| 192 | return gosnd->hw_ptr; | ||
| 193 | } | ||
| 194 | |||
| 195 | static struct page *go7007_snd_pcm_page(struct snd_pcm_substream *substream, | ||
| 196 | unsigned long offset) | ||
| 197 | { | ||
| 198 | return vmalloc_to_page(substream->runtime->dma_area + offset); | ||
| 199 | } | ||
| 200 | |||
| 201 | static struct snd_pcm_ops go7007_snd_capture_ops = { | ||
| 202 | .open = go7007_snd_capture_open, | ||
| 203 | .close = go7007_snd_capture_close, | ||
| 204 | .ioctl = snd_pcm_lib_ioctl, | ||
| 205 | .hw_params = go7007_snd_hw_params, | ||
| 206 | .hw_free = go7007_snd_hw_free, | ||
| 207 | .prepare = go7007_snd_pcm_prepare, | ||
| 208 | .trigger = go7007_snd_pcm_trigger, | ||
| 209 | .pointer = go7007_snd_pcm_pointer, | ||
| 210 | .page = go7007_snd_pcm_page, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int go7007_snd_free(struct snd_device *device) | ||
| 214 | { | ||
| 215 | struct go7007 *go = device->device_data; | ||
| 216 | |||
| 217 | kfree(go->snd_context); | ||
| 218 | go->snd_context = NULL; | ||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | static struct snd_device_ops go7007_snd_device_ops = { | ||
| 223 | .dev_free = go7007_snd_free, | ||
| 224 | }; | ||
| 225 | |||
| 226 | int go7007_snd_init(struct go7007 *go) | ||
| 227 | { | ||
| 228 | static int dev; | ||
| 229 | struct go7007_snd *gosnd; | ||
| 230 | int ret = 0; | ||
| 231 | |||
| 232 | if (dev >= SNDRV_CARDS) | ||
| 233 | return -ENODEV; | ||
| 234 | if (!enable[dev]) { | ||
| 235 | dev++; | ||
| 236 | return -ENOENT; | ||
| 237 | } | ||
| 238 | gosnd = kmalloc(sizeof(struct go7007_snd), GFP_KERNEL); | ||
| 239 | if (gosnd == NULL) | ||
| 240 | return -ENOMEM; | ||
| 241 | spin_lock_init(&gosnd->lock); | ||
| 242 | gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; | ||
| 243 | gosnd->capturing = 0; | ||
| 244 | ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0, | ||
| 245 | &gosnd->card); | ||
| 246 | if (ret < 0) { | ||
| 247 | kfree(gosnd); | ||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, | ||
| 251 | &go7007_snd_device_ops); | ||
| 252 | if (ret < 0) { | ||
| 253 | kfree(gosnd); | ||
| 254 | return ret; | ||
| 255 | } | ||
| 256 | ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm); | ||
| 257 | if (ret < 0) { | ||
| 258 | snd_card_free(gosnd->card); | ||
| 259 | kfree(gosnd); | ||
| 260 | return ret; | ||
| 261 | } | ||
| 262 | strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); | ||
| 263 | strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); | ||
| 264 | strlcpy(gosnd->card->longname, gosnd->card->shortname, | ||
| 265 | sizeof(gosnd->card->longname)); | ||
| 266 | |||
| 267 | gosnd->pcm->private_data = go; | ||
| 268 | snd_pcm_set_ops(gosnd->pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
| 269 | &go7007_snd_capture_ops); | ||
| 270 | |||
| 271 | ret = snd_card_register(gosnd->card); | ||
| 272 | if (ret < 0) { | ||
| 273 | snd_card_free(gosnd->card); | ||
| 274 | kfree(gosnd); | ||
| 275 | return ret; | ||
| 276 | } | ||
| 277 | |||
| 278 | gosnd->substream = NULL; | ||
| 279 | go->snd_context = gosnd; | ||
| 280 | v4l2_device_get(&go->v4l2_dev); | ||
| 281 | ++dev; | ||
| 282 | |||
| 283 | return 0; | ||
| 284 | } | ||
| 285 | EXPORT_SYMBOL(go7007_snd_init); | ||
| 286 | |||
| 287 | int go7007_snd_remove(struct go7007 *go) | ||
| 288 | { | ||
| 289 | struct go7007_snd *gosnd = go->snd_context; | ||
| 290 | |||
| 291 | snd_card_disconnect(gosnd->card); | ||
| 292 | snd_card_free_when_closed(gosnd->card); | ||
| 293 | v4l2_device_put(&go->v4l2_dev); | ||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | EXPORT_SYMBOL(go7007_snd_remove); | ||
| 297 | |||
| 298 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/media/usb/gspca/autogain_functions.c b/drivers/media/usb/gspca/autogain_functions.c index 67db674bb044..0e9ee8b50bb7 100644 --- a/drivers/media/usb/gspca/autogain_functions.c +++ b/drivers/media/usb/gspca/autogain_functions.c | |||
| @@ -121,9 +121,9 @@ int gspca_coarse_grained_expo_autogain( | |||
| 121 | orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain); | 121 | orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain); |
| 122 | orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure); | 122 | orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure); |
| 123 | 123 | ||
| 124 | gain_low = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) / | 124 | gain_low = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) / |
| 125 | 5 * 2 + gspca_dev->gain->minimum; | 125 | 5 * 2 + gspca_dev->gain->minimum; |
| 126 | gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) / | 126 | gain_high = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) / |
| 127 | 5 * 4 + gspca_dev->gain->minimum; | 127 | 5 * 4 + gspca_dev->gain->minimum; |
| 128 | 128 | ||
| 129 | /* If we are of a multiple of deadzone, do multiple steps to reach the | 129 | /* If we are of a multiple of deadzone, do multiple steps to reach the |
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index f3a7ace0fac9..e8cf23c91cef 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c | |||
| @@ -603,10 +603,13 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) | |||
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | /* | 605 | /* |
| 606 | * look for an input transfer endpoint in an alternate setting | 606 | * look for an input transfer endpoint in an alternate setting. |
| 607 | * | ||
| 608 | * If xfer_ep is invalid, return the first valid ep found, otherwise | ||
| 609 | * look for exactly the ep with address equal to xfer_ep. | ||
| 607 | */ | 610 | */ |
| 608 | static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, | 611 | static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, |
| 609 | int xfer) | 612 | int xfer, int xfer_ep) |
| 610 | { | 613 | { |
| 611 | struct usb_host_endpoint *ep; | 614 | struct usb_host_endpoint *ep; |
| 612 | int i, attr; | 615 | int i, attr; |
| @@ -616,7 +619,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt, | |||
| 616 | attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | 619 | attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; |
| 617 | if (attr == xfer | 620 | if (attr == xfer |
| 618 | && ep->desc.wMaxPacketSize != 0 | 621 | && ep->desc.wMaxPacketSize != 0 |
| 619 | && usb_endpoint_dir_in(&ep->desc)) | 622 | && usb_endpoint_dir_in(&ep->desc) |
| 623 | && (xfer_ep < 0 || ep->desc.bEndpointAddress == xfer_ep)) | ||
| 620 | return ep; | 624 | return ep; |
| 621 | } | 625 | } |
| 622 | return NULL; | 626 | return NULL; |
| @@ -689,7 +693,8 @@ static int build_isoc_ep_tb(struct gspca_dev *gspca_dev, | |||
| 689 | found = 0; | 693 | found = 0; |
| 690 | for (j = 0; j < nbalt; j++) { | 694 | for (j = 0; j < nbalt; j++) { |
| 691 | ep = alt_xfer(&intf->altsetting[j], | 695 | ep = alt_xfer(&intf->altsetting[j], |
| 692 | USB_ENDPOINT_XFER_ISOC); | 696 | USB_ENDPOINT_XFER_ISOC, |
| 697 | gspca_dev->xfer_ep); | ||
| 693 | if (ep == NULL) | 698 | if (ep == NULL) |
| 694 | continue; | 699 | continue; |
| 695 | if (ep->desc.bInterval == 0) { | 700 | if (ep->desc.bInterval == 0) { |
| @@ -862,7 +867,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
| 862 | /* if bulk or the subdriver forced an altsetting, get the endpoint */ | 867 | /* if bulk or the subdriver forced an altsetting, get the endpoint */ |
| 863 | if (gspca_dev->alt != 0) { | 868 | if (gspca_dev->alt != 0) { |
| 864 | gspca_dev->alt--; /* (previous version compatibility) */ | 869 | gspca_dev->alt--; /* (previous version compatibility) */ |
| 865 | ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); | 870 | ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer, |
| 871 | gspca_dev->xfer_ep); | ||
| 866 | if (ep == NULL) { | 872 | if (ep == NULL) { |
| 867 | pr_err("bad altsetting %d\n", gspca_dev->alt); | 873 | pr_err("bad altsetting %d\n", gspca_dev->alt); |
| 868 | return -EIO; | 874 | return -EIO; |
| @@ -904,7 +910,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
| 904 | if (!gspca_dev->cam.no_urb_create) { | 910 | if (!gspca_dev->cam.no_urb_create) { |
| 905 | PDEBUG(D_STREAM, "init transfer alt %d", alt); | 911 | PDEBUG(D_STREAM, "init transfer alt %d", alt); |
| 906 | ret = create_urbs(gspca_dev, | 912 | ret = create_urbs(gspca_dev, |
| 907 | alt_xfer(&intf->altsetting[alt], xfer)); | 913 | alt_xfer(&intf->altsetting[alt], xfer, |
| 914 | gspca_dev->xfer_ep)); | ||
| 908 | if (ret < 0) { | 915 | if (ret < 0) { |
| 909 | destroy_urbs(gspca_dev); | 916 | destroy_urbs(gspca_dev); |
| 910 | goto out; | 917 | goto out; |
| @@ -1102,8 +1109,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
| 1102 | struct gspca_dev *gspca_dev = video_drvdata(file); | 1109 | struct gspca_dev *gspca_dev = video_drvdata(file); |
| 1103 | 1110 | ||
| 1104 | fmt->fmt.pix = gspca_dev->pixfmt; | 1111 | fmt->fmt.pix = gspca_dev->pixfmt; |
| 1105 | /* some drivers use priv internally, zero it before giving it to | 1112 | /* some drivers use priv internally, zero it before giving it back to |
| 1106 | userspace */ | 1113 | the core */ |
| 1107 | fmt->fmt.pix.priv = 0; | 1114 | fmt->fmt.pix.priv = 0; |
| 1108 | return 0; | 1115 | return 0; |
| 1109 | } | 1116 | } |
| @@ -1139,8 +1146,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, | |||
| 1139 | fmt->fmt.pix.height = h; | 1146 | fmt->fmt.pix.height = h; |
| 1140 | gspca_dev->sd_desc->try_fmt(gspca_dev, fmt); | 1147 | gspca_dev->sd_desc->try_fmt(gspca_dev, fmt); |
| 1141 | } | 1148 | } |
| 1142 | /* some drivers use priv internally, zero it before giving it to | 1149 | /* some drivers use priv internally, zero it before giving it back to |
| 1143 | userspace */ | 1150 | the core */ |
| 1144 | fmt->fmt.pix.priv = 0; | 1151 | fmt->fmt.pix.priv = 0; |
| 1145 | return mode; /* used when s_fmt */ | 1152 | return mode; /* used when s_fmt */ |
| 1146 | } | 1153 | } |
| @@ -2030,6 +2037,7 @@ int gspca_dev_probe2(struct usb_interface *intf, | |||
| 2030 | } | 2037 | } |
| 2031 | gspca_dev->dev = dev; | 2038 | gspca_dev->dev = dev; |
| 2032 | gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; | 2039 | gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; |
| 2040 | gspca_dev->xfer_ep = -1; | ||
| 2033 | 2041 | ||
| 2034 | /* check if any audio device */ | 2042 | /* check if any audio device */ |
| 2035 | if (dev->actconfig->desc.bNumInterfaces != 1) { | 2043 | if (dev->actconfig->desc.bNumInterfaces != 1) { |
| @@ -2058,7 +2066,6 @@ int gspca_dev_probe2(struct usb_interface *intf, | |||
| 2058 | gspca_dev->vdev = gspca_template; | 2066 | gspca_dev->vdev = gspca_template; |
| 2059 | gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev; | 2067 | gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev; |
| 2060 | video_set_drvdata(&gspca_dev->vdev, gspca_dev); | 2068 | video_set_drvdata(&gspca_dev->vdev, gspca_dev); |
| 2061 | set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags); | ||
| 2062 | gspca_dev->module = module; | 2069 | gspca_dev->module = module; |
| 2063 | gspca_dev->present = 1; | 2070 | gspca_dev->present = 1; |
| 2064 | 2071 | ||
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h index 300642dc1a17..f06253cd7469 100644 --- a/drivers/media/usb/gspca/gspca.h +++ b/drivers/media/usb/gspca/gspca.h | |||
| @@ -205,6 +205,7 @@ struct gspca_dev { | |||
| 205 | char memory; /* memory type (V4L2_MEMORY_xxx) */ | 205 | char memory; /* memory type (V4L2_MEMORY_xxx) */ |
| 206 | __u8 iface; /* USB interface number */ | 206 | __u8 iface; /* USB interface number */ |
| 207 | __u8 alt; /* USB alternate setting */ | 207 | __u8 alt; /* USB alternate setting */ |
| 208 | int xfer_ep; /* USB transfer endpoint address */ | ||
| 208 | u8 audio; /* presence of audio device */ | 209 | u8 audio; /* presence of audio device */ |
| 209 | 210 | ||
| 210 | /* (*) These variables are proteced by both usb_lock and queue_lock, | 211 | /* (*) These variables are proteced by both usb_lock and queue_lock, |
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c index 081f05162809..45bc1f51c5d8 100644 --- a/drivers/media/usb/gspca/kinect.c +++ b/drivers/media/usb/gspca/kinect.c | |||
| @@ -36,6 +36,8 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | |||
| 36 | MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); | 36 | MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver"); |
| 37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
| 38 | 38 | ||
| 39 | static bool depth_mode; | ||
| 40 | |||
| 39 | struct pkt_hdr { | 41 | struct pkt_hdr { |
| 40 | uint8_t magic[2]; | 42 | uint8_t magic[2]; |
| 41 | uint8_t pad; | 43 | uint8_t pad; |
| @@ -73,6 +75,14 @@ struct sd { | |||
| 73 | 75 | ||
| 74 | #define FPS_HIGH 0x0100 | 76 | #define FPS_HIGH 0x0100 |
| 75 | 77 | ||
| 78 | static const struct v4l2_pix_format depth_camera_mode[] = { | ||
| 79 | {640, 480, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE, | ||
| 80 | .bytesperline = 640 * 10 / 8, | ||
| 81 | .sizeimage = 640 * 480 * 10 / 8, | ||
| 82 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
| 83 | .priv = MODE_640x488 | FORMAT_Y10B}, | ||
| 84 | }; | ||
| 85 | |||
| 76 | static const struct v4l2_pix_format video_camera_mode[] = { | 86 | static const struct v4l2_pix_format video_camera_mode[] = { |
| 77 | {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, | 87 | {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, |
| 78 | .bytesperline = 640, | 88 | .bytesperline = 640, |
| @@ -219,7 +229,7 @@ static int write_register(struct gspca_dev *gspca_dev, uint16_t reg, | |||
| 219 | } | 229 | } |
| 220 | 230 | ||
| 221 | /* this function is called at probe time */ | 231 | /* this function is called at probe time */ |
| 222 | static int sd_config(struct gspca_dev *gspca_dev, | 232 | static int sd_config_video(struct gspca_dev *gspca_dev, |
| 223 | const struct usb_device_id *id) | 233 | const struct usb_device_id *id) |
| 224 | { | 234 | { |
| 225 | struct sd *sd = (struct sd *) gspca_dev; | 235 | struct sd *sd = (struct sd *) gspca_dev; |
| @@ -227,8 +237,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 227 | 237 | ||
| 228 | sd->cam_tag = 0; | 238 | sd->cam_tag = 0; |
| 229 | 239 | ||
| 230 | /* Only video stream is supported for now, | ||
| 231 | * which has stream flag = 0x80 */ | ||
| 232 | sd->stream_flag = 0x80; | 240 | sd->stream_flag = 0x80; |
| 233 | 241 | ||
| 234 | cam = &gspca_dev->cam; | 242 | cam = &gspca_dev->cam; |
| @@ -236,6 +244,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 236 | cam->cam_mode = video_camera_mode; | 244 | cam->cam_mode = video_camera_mode; |
| 237 | cam->nmodes = ARRAY_SIZE(video_camera_mode); | 245 | cam->nmodes = ARRAY_SIZE(video_camera_mode); |
| 238 | 246 | ||
| 247 | gspca_dev->xfer_ep = 0x81; | ||
| 248 | |||
| 239 | #if 0 | 249 | #if 0 |
| 240 | /* Setting those values is not needed for video stream */ | 250 | /* Setting those values is not needed for video stream */ |
| 241 | cam->npkt = 15; | 251 | cam->npkt = 15; |
| @@ -245,6 +255,26 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
| 245 | return 0; | 255 | return 0; |
| 246 | } | 256 | } |
| 247 | 257 | ||
| 258 | static int sd_config_depth(struct gspca_dev *gspca_dev, | ||
| 259 | const struct usb_device_id *id) | ||
| 260 | { | ||
| 261 | struct sd *sd = (struct sd *) gspca_dev; | ||
| 262 | struct cam *cam; | ||
| 263 | |||
| 264 | sd->cam_tag = 0; | ||
| 265 | |||
| 266 | sd->stream_flag = 0x70; | ||
| 267 | |||
| 268 | cam = &gspca_dev->cam; | ||
| 269 | |||
| 270 | cam->cam_mode = depth_camera_mode; | ||
| 271 | cam->nmodes = ARRAY_SIZE(depth_camera_mode); | ||
| 272 | |||
| 273 | gspca_dev->xfer_ep = 0x82; | ||
| 274 | |||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | |||
| 248 | /* this function is called at probe and resume time */ | 278 | /* this function is called at probe and resume time */ |
| 249 | static int sd_init(struct gspca_dev *gspca_dev) | 279 | static int sd_init(struct gspca_dev *gspca_dev) |
| 250 | { | 280 | { |
| @@ -253,7 +283,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
| 253 | return 0; | 283 | return 0; |
| 254 | } | 284 | } |
| 255 | 285 | ||
| 256 | static int sd_start(struct gspca_dev *gspca_dev) | 286 | static int sd_start_video(struct gspca_dev *gspca_dev) |
| 257 | { | 287 | { |
| 258 | int mode; | 288 | int mode; |
| 259 | uint8_t fmt_reg, fmt_val; | 289 | uint8_t fmt_reg, fmt_val; |
| @@ -325,12 +355,39 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
| 325 | return 0; | 355 | return 0; |
| 326 | } | 356 | } |
| 327 | 357 | ||
| 328 | static void sd_stopN(struct gspca_dev *gspca_dev) | 358 | static int sd_start_depth(struct gspca_dev *gspca_dev) |
| 359 | { | ||
| 360 | /* turn off IR-reset function */ | ||
| 361 | write_register(gspca_dev, 0x105, 0x00); | ||
| 362 | |||
| 363 | /* reset depth stream */ | ||
| 364 | write_register(gspca_dev, 0x06, 0x00); | ||
| 365 | /* Depth Stream Format 0x03: 11 bit stream | 0x02: 10 bit */ | ||
| 366 | write_register(gspca_dev, 0x12, 0x02); | ||
| 367 | /* Depth Stream Resolution 1: standard (640x480) */ | ||
| 368 | write_register(gspca_dev, 0x13, 0x01); | ||
| 369 | /* Depth Framerate / 0x1e (30): 30 fps */ | ||
| 370 | write_register(gspca_dev, 0x14, 0x1e); | ||
| 371 | /* Depth Stream Control / 2: Open Depth Stream */ | ||
| 372 | write_register(gspca_dev, 0x06, 0x02); | ||
| 373 | /* disable depth hflip / LSB = 0: Smoothing Disabled */ | ||
| 374 | write_register(gspca_dev, 0x17, 0x00); | ||
| 375 | |||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | static void sd_stopN_video(struct gspca_dev *gspca_dev) | ||
| 329 | { | 380 | { |
| 330 | /* reset video stream */ | 381 | /* reset video stream */ |
| 331 | write_register(gspca_dev, 0x05, 0x00); | 382 | write_register(gspca_dev, 0x05, 0x00); |
| 332 | } | 383 | } |
| 333 | 384 | ||
| 385 | static void sd_stopN_depth(struct gspca_dev *gspca_dev) | ||
| 386 | { | ||
| 387 | /* reset depth stream */ | ||
| 388 | write_register(gspca_dev, 0x06, 0x00); | ||
| 389 | } | ||
| 390 | |||
| 334 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len) | 391 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len) |
| 335 | { | 392 | { |
| 336 | struct sd *sd = (struct sd *) gspca_dev; | 393 | struct sd *sd = (struct sd *) gspca_dev; |
| @@ -366,12 +423,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len) | |||
| 366 | } | 423 | } |
| 367 | 424 | ||
| 368 | /* sub-driver description */ | 425 | /* sub-driver description */ |
| 369 | static const struct sd_desc sd_desc = { | 426 | static const struct sd_desc sd_desc_video = { |
| 370 | .name = MODULE_NAME, | 427 | .name = MODULE_NAME, |
| 371 | .config = sd_config, | 428 | .config = sd_config_video, |
| 372 | .init = sd_init, | 429 | .init = sd_init, |
| 373 | .start = sd_start, | 430 | .start = sd_start_video, |
| 374 | .stopN = sd_stopN, | 431 | .stopN = sd_stopN_video, |
| 432 | .pkt_scan = sd_pkt_scan, | ||
| 433 | /* | ||
| 434 | .get_streamparm = sd_get_streamparm, | ||
| 435 | .set_streamparm = sd_set_streamparm, | ||
| 436 | */ | ||
| 437 | }; | ||
| 438 | static const struct sd_desc sd_desc_depth = { | ||
| 439 | .name = MODULE_NAME, | ||
| 440 | .config = sd_config_depth, | ||
| 441 | .init = sd_init, | ||
| 442 | .start = sd_start_depth, | ||
| 443 | .stopN = sd_stopN_depth, | ||
| 375 | .pkt_scan = sd_pkt_scan, | 444 | .pkt_scan = sd_pkt_scan, |
| 376 | /* | 445 | /* |
| 377 | .get_streamparm = sd_get_streamparm, | 446 | .get_streamparm = sd_get_streamparm, |
| @@ -391,8 +460,12 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
| 391 | /* -- device connect -- */ | 460 | /* -- device connect -- */ |
| 392 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) | 461 | static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 393 | { | 462 | { |
| 394 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | 463 | if (depth_mode) |
| 395 | THIS_MODULE); | 464 | return gspca_dev_probe(intf, id, &sd_desc_depth, |
| 465 | sizeof(struct sd), THIS_MODULE); | ||
| 466 | else | ||
| 467 | return gspca_dev_probe(intf, id, &sd_desc_video, | ||
| 468 | sizeof(struct sd), THIS_MODULE); | ||
| 396 | } | 469 | } |
| 397 | 470 | ||
| 398 | static struct usb_driver sd_driver = { | 471 | static struct usb_driver sd_driver = { |
| @@ -408,3 +481,6 @@ static struct usb_driver sd_driver = { | |||
| 408 | }; | 481 | }; |
| 409 | 482 | ||
| 410 | module_usb_driver(sd_driver); | 483 | module_usb_driver(sd_driver); |
| 484 | |||
| 485 | module_param(depth_mode, bool, 0644); | ||
| 486 | MODULE_PARM_DESC(depth_mode, "0=video 1=depth"); | ||
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index 339adce7c7a5..8b08bd0172f4 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c | |||
| @@ -394,9 +394,9 @@ static void setbrightcont(struct gspca_dev *gspca_dev) | |||
| 394 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 394 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
| 395 | for (i = 0; i < 10; i++) { | 395 | for (i = 0; i < 10; i++) { |
| 396 | v = max[i]; | 396 | v = max[i]; |
| 397 | v += (sd->brightness->val - sd->brightness->maximum) | 397 | v += (sd->brightness->val - (s32)sd->brightness->maximum) |
| 398 | * 150 / sd->brightness->maximum; /* 200 ? */ | 398 | * 150 / (s32)sd->brightness->maximum; /* 200 ? */ |
| 399 | v -= delta[i] * sd->contrast->val / sd->contrast->maximum; | 399 | v -= delta[i] * sd->contrast->val / (s32)sd->contrast->maximum; |
| 400 | if (v < 0) | 400 | if (v < 0) |
| 401 | v = 0; | 401 | v = 0; |
| 402 | else if (v > 0xff) | 402 | else if (v > 0xff) |
| @@ -419,7 +419,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
| 419 | reg_w(gspca_dev, 0x11, 0x01); | 419 | reg_w(gspca_dev, 0x11, 0x01); |
| 420 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ | 420 | reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ |
| 421 | for (i = 0; i < 9; i++) { | 421 | for (i = 0; i < 9; i++) { |
| 422 | v = a[i] * sd->saturation->val / sd->saturation->maximum; | 422 | v = a[i] * sd->saturation->val / (s32)sd->saturation->maximum; |
| 423 | v += b[i]; | 423 | v += b[i]; |
| 424 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); | 424 | reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); |
| 425 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); | 425 | reg_w(gspca_dev, 0x0f + 2 * i + 1, v); |
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index ecbcb39feb71..6696b2ec34e9 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c | |||
| @@ -913,7 +913,7 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
| 913 | desired_avg_lum, deadzone)) | 913 | desired_avg_lum, deadzone)) |
| 914 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | 914 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
| 915 | } else { | 915 | } else { |
| 916 | int gain_knee = gspca_dev->gain->maximum * 9 / 10; | 916 | int gain_knee = (s32)gspca_dev->gain->maximum * 9 / 10; |
| 917 | if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum, | 917 | if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum, |
| 918 | deadzone, gain_knee, sd->exposure_knee)) | 918 | deadzone, gain_knee, sd->exposure_knee)) |
| 919 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | 919 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 6bce01a674f9..59d15fd242ba 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c | |||
| @@ -1022,14 +1022,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, | |||
| 1022 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 1022 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
| 1023 | f->fmt.pix.sizeimage = dev->bulk_in_size; | 1023 | f->fmt.pix.sizeimage = dev->bulk_in_size; |
| 1024 | f->fmt.pix.bytesperline = 0; | 1024 | f->fmt.pix.bytesperline = 0; |
| 1025 | f->fmt.pix.priv = 0; | ||
| 1026 | if (f->fmt.pix.width == 720) { | 1025 | if (f->fmt.pix.width == 720) { |
| 1027 | /* SDTV formats */ | 1026 | /* SDTV formats */ |
| 1028 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 1027 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
| 1029 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | 1028 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; |
| 1030 | } else { | 1029 | } else { |
| 1031 | /* HDTV formats */ | 1030 | /* HDTV formats */ |
| 1032 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE240M; | 1031 | f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709; |
| 1033 | f->fmt.pix.field = V4L2_FIELD_NONE; | 1032 | f->fmt.pix.field = V4L2_FIELD_NONE; |
| 1034 | } | 1033 | } |
| 1035 | return 0; | 1034 | return 0; |
| @@ -1240,7 +1239,6 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, | |||
| 1240 | strcpy(dev->video_dev->name, "Hauppauge HD PVR"); | 1239 | strcpy(dev->video_dev->name, "Hauppauge HD PVR"); |
| 1241 | dev->video_dev->v4l2_dev = &dev->v4l2_dev; | 1240 | dev->video_dev->v4l2_dev = &dev->v4l2_dev; |
| 1242 | video_set_drvdata(dev->video_dev, dev); | 1241 | video_set_drvdata(dev->video_dev, dev); |
| 1243 | set_bit(V4L2_FL_USE_FH_PRIO, &dev->video_dev->flags); | ||
| 1244 | 1242 | ||
| 1245 | res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); | 1243 | res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum); |
| 1246 | if (res < 0) { | 1244 | if (res < 0) { |
diff --git a/drivers/media/usb/msi2500/Kconfig b/drivers/media/usb/msi2500/Kconfig new file mode 100644 index 000000000000..9eff8a76ff0e --- /dev/null +++ b/drivers/media/usb/msi2500/Kconfig | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | config USB_MSI2500 | ||
| 2 | tristate "Mirics MSi2500" | ||
| 3 | depends on VIDEO_V4L2 && SPI | ||
| 4 | select VIDEOBUF2_VMALLOC | ||
| 5 | select MEDIA_TUNER_MSI001 | ||
diff --git a/drivers/media/usb/msi2500/Makefile b/drivers/media/usb/msi2500/Makefile new file mode 100644 index 000000000000..b3bc2e53707f --- /dev/null +++ b/drivers/media/usb/msi2500/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-$(CONFIG_USB_MSI2500) += msi2500.o | |||
diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c new file mode 100644 index 000000000000..26b133414032 --- /dev/null +++ b/drivers/media/usb/msi2500/msi2500.c | |||
| @@ -0,0 +1,1336 @@ | |||
| 1 | /* | ||
| 2 | * Mirics MSi3101 SDR Dongle driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Antti Palosaari <crope@iki.fi> | ||
| 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, or | ||
| 9 | * (at your option) any later version. | ||
| 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 along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 19 | * | ||
| 20 | * That driver is somehow based of pwc driver: | ||
| 21 | * (C) 1999-2004 Nemosoft Unv. | ||
| 22 | * (C) 2004-2006 Luc Saillard (luc@saillard.org) | ||
| 23 | * (C) 2011 Hans de Goede <hdegoede@redhat.com> | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <asm/div64.h> | ||
| 29 | #include <media/v4l2-device.h> | ||
| 30 | #include <media/v4l2-ioctl.h> | ||
| 31 | #include <media/v4l2-ctrls.h> | ||
| 32 | #include <media/v4l2-event.h> | ||
| 33 | #include <linux/usb.h> | ||
| 34 | #include <media/videobuf2-vmalloc.h> | ||
| 35 | #include <linux/spi/spi.h> | ||
| 36 | |||
| 37 | static bool msi2500_emulated_fmt; | ||
| 38 | module_param_named(emulated_formats, msi2500_emulated_fmt, bool, 0644); | ||
| 39 | MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)"); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * iConfiguration 0 | ||
| 43 | * bInterfaceNumber 0 | ||
| 44 | * bAlternateSetting 1 | ||
| 45 | * bNumEndpoints 1 | ||
| 46 | * bEndpointAddress 0x81 EP 1 IN | ||
| 47 | * bmAttributes 1 | ||
| 48 | * Transfer Type Isochronous | ||
| 49 | * wMaxPacketSize 0x1400 3x 1024 bytes | ||
| 50 | * bInterval 1 | ||
| 51 | */ | ||
| 52 | #define MAX_ISO_BUFS (8) | ||
| 53 | #define ISO_FRAMES_PER_DESC (8) | ||
| 54 | #define ISO_MAX_FRAME_SIZE (3 * 1024) | ||
| 55 | #define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) | ||
| 56 | #define MAX_ISOC_ERRORS 20 | ||
| 57 | |||
| 58 | /* | ||
| 59 | * TODO: These formats should be moved to V4L2 API. Formats are currently | ||
| 60 | * disabled from formats[] table, not visible to userspace. | ||
| 61 | */ | ||
| 62 | /* signed 12-bit */ | ||
| 63 | #define MSI2500_PIX_FMT_SDR_S12 v4l2_fourcc('D', 'S', '1', '2') | ||
| 64 | /* Mirics MSi2500 format 384 */ | ||
| 65 | #define MSI2500_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') | ||
| 66 | |||
| 67 | static const struct v4l2_frequency_band bands[] = { | ||
| 68 | { | ||
| 69 | .tuner = 0, | ||
| 70 | .type = V4L2_TUNER_ADC, | ||
| 71 | .index = 0, | ||
| 72 | .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS, | ||
| 73 | .rangelow = 1200000, | ||
| 74 | .rangehigh = 15000000, | ||
| 75 | }, | ||
| 76 | }; | ||
| 77 | |||
| 78 | /* stream formats */ | ||
| 79 | struct msi2500_format { | ||
| 80 | char *name; | ||
| 81 | u32 pixelformat; | ||
| 82 | u32 buffersize; | ||
| 83 | }; | ||
| 84 | |||
| 85 | /* format descriptions for capture and preview */ | ||
| 86 | static struct msi2500_format formats[] = { | ||
| 87 | { | ||
| 88 | .name = "Complex S8", | ||
| 89 | .pixelformat = V4L2_SDR_FMT_CS8, | ||
| 90 | .buffersize = 3 * 1008, | ||
| 91 | #if 0 | ||
| 92 | }, { | ||
| 93 | .name = "10+2-bit signed", | ||
| 94 | .pixelformat = MSI2500_PIX_FMT_SDR_MSI2500_384, | ||
| 95 | }, { | ||
| 96 | .name = "12-bit signed", | ||
| 97 | .pixelformat = MSI2500_PIX_FMT_SDR_S12, | ||
| 98 | #endif | ||
| 99 | }, { | ||
| 100 | .name = "Complex S14LE", | ||
| 101 | .pixelformat = V4L2_SDR_FMT_CS14LE, | ||
| 102 | .buffersize = 3 * 1008, | ||
| 103 | }, { | ||
| 104 | .name = "Complex U8 (emulated)", | ||
| 105 | .pixelformat = V4L2_SDR_FMT_CU8, | ||
| 106 | .buffersize = 3 * 1008, | ||
| 107 | }, { | ||
| 108 | .name = "Complex U16LE (emulated)", | ||
| 109 | .pixelformat = V4L2_SDR_FMT_CU16LE, | ||
| 110 | .buffersize = 3 * 1008, | ||
| 111 | }, | ||
| 112 | }; | ||
| 113 | |||
| 114 | static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats); | ||
| 115 | |||
| 116 | /* intermediate buffers with raw data from the USB device */ | ||
| 117 | struct msi2500_frame_buf { | ||
| 118 | struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */ | ||
| 119 | struct list_head list; | ||
| 120 | }; | ||
| 121 | |||
| 122 | struct msi2500_state { | ||
| 123 | struct video_device vdev; | ||
| 124 | struct v4l2_device v4l2_dev; | ||
| 125 | struct v4l2_subdev *v4l2_subdev; | ||
| 126 | struct spi_master *master; | ||
| 127 | |||
| 128 | /* videobuf2 queue and queued buffers list */ | ||
| 129 | struct vb2_queue vb_queue; | ||
| 130 | struct list_head queued_bufs; | ||
| 131 | spinlock_t queued_bufs_lock; /* Protects queued_bufs */ | ||
| 132 | |||
| 133 | /* Note if taking both locks v4l2_lock must always be locked first! */ | ||
| 134 | struct mutex v4l2_lock; /* Protects everything else */ | ||
| 135 | struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */ | ||
| 136 | |||
| 137 | /* Pointer to our usb_device, will be NULL after unplug */ | ||
| 138 | struct usb_device *udev; /* Both mutexes most be hold when setting! */ | ||
| 139 | |||
| 140 | unsigned int f_adc; | ||
| 141 | u32 pixelformat; | ||
| 142 | u32 buffersize; | ||
| 143 | unsigned int num_formats; | ||
| 144 | |||
| 145 | unsigned int isoc_errors; /* number of contiguous ISOC errors */ | ||
| 146 | unsigned int vb_full; /* vb is full and packets dropped */ | ||
| 147 | |||
| 148 | struct urb *urbs[MAX_ISO_BUFS]; | ||
| 149 | |||
| 150 | /* Controls */ | ||
| 151 | struct v4l2_ctrl_handler hdl; | ||
| 152 | |||
| 153 | u32 next_sample; /* for track lost packets */ | ||
| 154 | u32 sample; /* for sample rate calc */ | ||
| 155 | unsigned long jiffies_next; | ||
| 156 | unsigned int sample_ctrl_bit[4]; | ||
| 157 | }; | ||
| 158 | |||
| 159 | /* Private functions */ | ||
| 160 | static struct msi2500_frame_buf *msi2500_get_next_fill_buf( | ||
| 161 | struct msi2500_state *s) | ||
| 162 | { | ||
| 163 | unsigned long flags = 0; | ||
| 164 | struct msi2500_frame_buf *buf = NULL; | ||
| 165 | |||
| 166 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 167 | if (list_empty(&s->queued_bufs)) | ||
| 168 | goto leave; | ||
| 169 | |||
| 170 | buf = list_entry(s->queued_bufs.next, struct msi2500_frame_buf, list); | ||
| 171 | list_del(&buf->list); | ||
| 172 | leave: | ||
| 173 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 174 | return buf; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* | ||
| 178 | * +=========================================================================== | ||
| 179 | * | 00-1023 | USB packet type '504' | ||
| 180 | * +=========================================================================== | ||
| 181 | * | 00- 03 | sequence number of first sample in that USB packet | ||
| 182 | * +--------------------------------------------------------------------------- | ||
| 183 | * | 04- 15 | garbage | ||
| 184 | * +--------------------------------------------------------------------------- | ||
| 185 | * | 16-1023 | samples | ||
| 186 | * +--------------------------------------------------------------------------- | ||
| 187 | * signed 8-bit sample | ||
| 188 | * 504 * 2 = 1008 samples | ||
| 189 | * | ||
| 190 | * | ||
| 191 | * +=========================================================================== | ||
| 192 | * | 00-1023 | USB packet type '384' | ||
| 193 | * +=========================================================================== | ||
| 194 | * | 00- 03 | sequence number of first sample in that USB packet | ||
| 195 | * +--------------------------------------------------------------------------- | ||
| 196 | * | 04- 15 | garbage | ||
| 197 | * +--------------------------------------------------------------------------- | ||
| 198 | * | 16- 175 | samples | ||
| 199 | * +--------------------------------------------------------------------------- | ||
| 200 | * | 176- 179 | control bits for previous samples | ||
| 201 | * +--------------------------------------------------------------------------- | ||
| 202 | * | 180- 339 | samples | ||
| 203 | * +--------------------------------------------------------------------------- | ||
| 204 | * | 340- 343 | control bits for previous samples | ||
| 205 | * +--------------------------------------------------------------------------- | ||
| 206 | * | 344- 503 | samples | ||
| 207 | * +--------------------------------------------------------------------------- | ||
| 208 | * | 504- 507 | control bits for previous samples | ||
| 209 | * +--------------------------------------------------------------------------- | ||
| 210 | * | 508- 667 | samples | ||
| 211 | * +--------------------------------------------------------------------------- | ||
| 212 | * | 668- 671 | control bits for previous samples | ||
| 213 | * +--------------------------------------------------------------------------- | ||
| 214 | * | 672- 831 | samples | ||
| 215 | * +--------------------------------------------------------------------------- | ||
| 216 | * | 832- 835 | control bits for previous samples | ||
| 217 | * +--------------------------------------------------------------------------- | ||
| 218 | * | 836- 995 | samples | ||
| 219 | * +--------------------------------------------------------------------------- | ||
| 220 | * | 996- 999 | control bits for previous samples | ||
| 221 | * +--------------------------------------------------------------------------- | ||
| 222 | * | 1000-1023 | garbage | ||
| 223 | * +--------------------------------------------------------------------------- | ||
| 224 | * | ||
| 225 | * Bytes 4 - 7 could have some meaning? | ||
| 226 | * | ||
| 227 | * Control bits for previous samples is 32-bit field, containing 16 x 2-bit | ||
| 228 | * numbers. This results one 2-bit number for 8 samples. It is likely used for | ||
| 229 | * for bit shifting sample by given bits, increasing actual sampling resolution. | ||
| 230 | * Number 2 (0b10) was never seen. | ||
| 231 | * | ||
| 232 | * 6 * 16 * 2 * 4 = 768 samples. 768 * 4 = 3072 bytes | ||
| 233 | * | ||
| 234 | * | ||
| 235 | * +=========================================================================== | ||
| 236 | * | 00-1023 | USB packet type '336' | ||
| 237 | * +=========================================================================== | ||
| 238 | * | 00- 03 | sequence number of first sample in that USB packet | ||
| 239 | * +--------------------------------------------------------------------------- | ||
| 240 | * | 04- 15 | garbage | ||
| 241 | * +--------------------------------------------------------------------------- | ||
| 242 | * | 16-1023 | samples | ||
| 243 | * +--------------------------------------------------------------------------- | ||
| 244 | * signed 12-bit sample | ||
| 245 | * | ||
| 246 | * | ||
| 247 | * +=========================================================================== | ||
| 248 | * | 00-1023 | USB packet type '252' | ||
| 249 | * +=========================================================================== | ||
| 250 | * | 00- 03 | sequence number of first sample in that USB packet | ||
| 251 | * +--------------------------------------------------------------------------- | ||
| 252 | * | 04- 15 | garbage | ||
| 253 | * +--------------------------------------------------------------------------- | ||
| 254 | * | 16-1023 | samples | ||
| 255 | * +--------------------------------------------------------------------------- | ||
| 256 | * signed 14-bit sample | ||
| 257 | */ | ||
| 258 | |||
| 259 | static int msi2500_convert_stream(struct msi2500_state *s, u8 *dst, u8 *src, | ||
| 260 | unsigned int src_len) | ||
| 261 | { | ||
| 262 | unsigned int i, j, transactions, dst_len = 0; | ||
| 263 | u32 sample[3]; | ||
| 264 | |||
| 265 | /* There could be 1-3 1024 byte transactions per packet */ | ||
| 266 | transactions = src_len / 1024; | ||
| 267 | |||
| 268 | for (i = 0; i < transactions; i++) { | ||
| 269 | sample[i] = src[3] << 24 | src[2] << 16 | src[1] << 8 | | ||
| 270 | src[0] << 0; | ||
| 271 | if (i == 0 && s->next_sample != sample[0]) { | ||
| 272 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 273 | "%d samples lost, %d %08x:%08x\n", | ||
| 274 | sample[0] - s->next_sample, | ||
| 275 | src_len, s->next_sample, sample[0]); | ||
| 276 | } | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Dump all unknown 'garbage' data - maybe we will discover | ||
| 280 | * someday if there is something rational... | ||
| 281 | */ | ||
| 282 | dev_dbg_ratelimited(&s->udev->dev, "%*ph\n", 12, &src[4]); | ||
| 283 | |||
| 284 | src += 16; /* skip header */ | ||
| 285 | |||
| 286 | switch (s->pixelformat) { | ||
| 287 | case V4L2_SDR_FMT_CU8: /* 504 x IQ samples */ | ||
| 288 | { | ||
| 289 | s8 *s8src = (s8 *) src; | ||
| 290 | u8 *u8dst = (u8 *) dst; | ||
| 291 | |||
| 292 | for (j = 0; j < 1008; j++) | ||
| 293 | *u8dst++ = *s8src++ + 128; | ||
| 294 | |||
| 295 | src += 1008; | ||
| 296 | dst += 1008; | ||
| 297 | dst_len += 1008; | ||
| 298 | s->next_sample = sample[i] + 504; | ||
| 299 | break; | ||
| 300 | } | ||
| 301 | case V4L2_SDR_FMT_CU16LE: /* 252 x IQ samples */ | ||
| 302 | { | ||
| 303 | s16 *s16src = (s16 *) src; | ||
| 304 | u16 *u16dst = (u16 *) dst; | ||
| 305 | struct {signed int x:14; } se; /* sign extension */ | ||
| 306 | unsigned int utmp; | ||
| 307 | |||
| 308 | for (j = 0; j < 1008; j += 2) { | ||
| 309 | /* sign extension from 14-bit to signed int */ | ||
| 310 | se.x = *s16src++; | ||
| 311 | /* from signed int to unsigned int */ | ||
| 312 | utmp = se.x + 8192; | ||
| 313 | /* from 14-bit to 16-bit */ | ||
| 314 | *u16dst++ = utmp << 2 | utmp >> 12; | ||
| 315 | } | ||
| 316 | |||
| 317 | src += 1008; | ||
| 318 | dst += 1008; | ||
| 319 | dst_len += 1008; | ||
| 320 | s->next_sample = sample[i] + 252; | ||
| 321 | break; | ||
| 322 | } | ||
| 323 | case MSI2500_PIX_FMT_SDR_MSI2500_384: /* 384 x IQ samples */ | ||
| 324 | /* Dump unknown 'garbage' data */ | ||
| 325 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 326 | "%*ph\n", 24, &src[1000]); | ||
| 327 | memcpy(dst, src, 984); | ||
| 328 | src += 984 + 24; | ||
| 329 | dst += 984; | ||
| 330 | dst_len += 984; | ||
| 331 | s->next_sample = sample[i] + 384; | ||
| 332 | break; | ||
| 333 | case V4L2_SDR_FMT_CS8: /* 504 x IQ samples */ | ||
| 334 | memcpy(dst, src, 1008); | ||
| 335 | src += 1008; | ||
| 336 | dst += 1008; | ||
| 337 | dst_len += 1008; | ||
| 338 | s->next_sample = sample[i] + 504; | ||
| 339 | break; | ||
| 340 | case MSI2500_PIX_FMT_SDR_S12: /* 336 x IQ samples */ | ||
| 341 | memcpy(dst, src, 1008); | ||
| 342 | src += 1008; | ||
| 343 | dst += 1008; | ||
| 344 | dst_len += 1008; | ||
| 345 | s->next_sample = sample[i] + 336; | ||
| 346 | break; | ||
| 347 | case V4L2_SDR_FMT_CS14LE: /* 252 x IQ samples */ | ||
| 348 | memcpy(dst, src, 1008); | ||
| 349 | src += 1008; | ||
| 350 | dst += 1008; | ||
| 351 | dst_len += 1008; | ||
| 352 | s->next_sample = sample[i] + 252; | ||
| 353 | break; | ||
| 354 | default: | ||
| 355 | break; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | /* calculate sample rate and output it in 10 seconds intervals */ | ||
| 360 | if (unlikely(time_is_before_jiffies(s->jiffies_next))) { | ||
| 361 | #define MSECS 10000UL | ||
| 362 | unsigned int msecs = jiffies_to_msecs(jiffies - | ||
| 363 | s->jiffies_next + msecs_to_jiffies(MSECS)); | ||
| 364 | unsigned int samples = s->next_sample - s->sample; | ||
| 365 | |||
| 366 | s->jiffies_next = jiffies + msecs_to_jiffies(MSECS); | ||
| 367 | s->sample = s->next_sample; | ||
| 368 | dev_dbg(&s->udev->dev, | ||
| 369 | "size=%u samples=%u msecs=%u sample rate=%lu\n", | ||
| 370 | src_len, samples, msecs, | ||
| 371 | samples * 1000UL / msecs); | ||
| 372 | } | ||
| 373 | |||
| 374 | return dst_len; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* | ||
| 378 | * This gets called for the Isochronous pipe (stream). This is done in interrupt | ||
| 379 | * time, so it has to be fast, not crash, and not stall. Neat. | ||
| 380 | */ | ||
| 381 | static void msi2500_isoc_handler(struct urb *urb) | ||
| 382 | { | ||
| 383 | struct msi2500_state *s = (struct msi2500_state *)urb->context; | ||
| 384 | int i, flen, fstatus; | ||
| 385 | unsigned char *iso_buf = NULL; | ||
| 386 | struct msi2500_frame_buf *fbuf; | ||
| 387 | |||
| 388 | if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || | ||
| 389 | urb->status == -ESHUTDOWN)) { | ||
| 390 | dev_dbg(&s->udev->dev, "URB (%p) unlinked %ssynchronuously\n", | ||
| 391 | urb, urb->status == -ENOENT ? "" : "a"); | ||
| 392 | return; | ||
| 393 | } | ||
| 394 | |||
| 395 | if (unlikely(urb->status != 0)) { | ||
| 396 | dev_dbg(&s->udev->dev, | ||
| 397 | "msi2500_isoc_handler() called with status %d\n", | ||
| 398 | urb->status); | ||
| 399 | /* Give up after a number of contiguous errors */ | ||
| 400 | if (++s->isoc_errors > MAX_ISOC_ERRORS) | ||
| 401 | dev_dbg(&s->udev->dev, | ||
| 402 | "Too many ISOC errors, bailing out\n"); | ||
| 403 | goto handler_end; | ||
| 404 | } else { | ||
| 405 | /* Reset ISOC error counter. We did get here, after all. */ | ||
| 406 | s->isoc_errors = 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | /* Compact data */ | ||
| 410 | for (i = 0; i < urb->number_of_packets; i++) { | ||
| 411 | void *ptr; | ||
| 412 | |||
| 413 | /* Check frame error */ | ||
| 414 | fstatus = urb->iso_frame_desc[i].status; | ||
| 415 | if (unlikely(fstatus)) { | ||
| 416 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 417 | "frame=%d/%d has error %d skipping\n", | ||
| 418 | i, urb->number_of_packets, fstatus); | ||
| 419 | continue; | ||
| 420 | } | ||
| 421 | |||
| 422 | /* Check if that frame contains data */ | ||
| 423 | flen = urb->iso_frame_desc[i].actual_length; | ||
| 424 | if (unlikely(flen == 0)) | ||
| 425 | continue; | ||
| 426 | |||
| 427 | iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
| 428 | |||
| 429 | /* Get free framebuffer */ | ||
| 430 | fbuf = msi2500_get_next_fill_buf(s); | ||
| 431 | if (unlikely(fbuf == NULL)) { | ||
| 432 | s->vb_full++; | ||
| 433 | dev_dbg_ratelimited(&s->udev->dev, | ||
| 434 | "videobuf is full, %d packets dropped\n", | ||
| 435 | s->vb_full); | ||
| 436 | continue; | ||
| 437 | } | ||
| 438 | |||
| 439 | /* fill framebuffer */ | ||
| 440 | ptr = vb2_plane_vaddr(&fbuf->vb, 0); | ||
| 441 | flen = msi2500_convert_stream(s, ptr, iso_buf, flen); | ||
| 442 | vb2_set_plane_payload(&fbuf->vb, 0, flen); | ||
| 443 | vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE); | ||
| 444 | } | ||
| 445 | |||
| 446 | handler_end: | ||
| 447 | i = usb_submit_urb(urb, GFP_ATOMIC); | ||
| 448 | if (unlikely(i != 0)) | ||
| 449 | dev_dbg(&s->udev->dev, | ||
| 450 | "Error (%d) re-submitting urb in msi2500_isoc_handler\n", | ||
| 451 | i); | ||
| 452 | } | ||
| 453 | |||
| 454 | static void msi2500_iso_stop(struct msi2500_state *s) | ||
| 455 | { | ||
| 456 | int i; | ||
| 457 | |||
| 458 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 459 | |||
| 460 | /* Unlinking ISOC buffers one by one */ | ||
| 461 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 462 | if (s->urbs[i]) { | ||
| 463 | dev_dbg(&s->udev->dev, "Unlinking URB %p\n", | ||
| 464 | s->urbs[i]); | ||
| 465 | usb_kill_urb(s->urbs[i]); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | static void msi2500_iso_free(struct msi2500_state *s) | ||
| 471 | { | ||
| 472 | int i; | ||
| 473 | |||
| 474 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 475 | |||
| 476 | /* Freeing ISOC buffers one by one */ | ||
| 477 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 478 | if (s->urbs[i]) { | ||
| 479 | dev_dbg(&s->udev->dev, "Freeing URB\n"); | ||
| 480 | if (s->urbs[i]->transfer_buffer) { | ||
| 481 | usb_free_coherent(s->udev, | ||
| 482 | s->urbs[i]->transfer_buffer_length, | ||
| 483 | s->urbs[i]->transfer_buffer, | ||
| 484 | s->urbs[i]->transfer_dma); | ||
| 485 | } | ||
| 486 | usb_free_urb(s->urbs[i]); | ||
| 487 | s->urbs[i] = NULL; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | } | ||
| 491 | |||
| 492 | /* Both v4l2_lock and vb_queue_lock should be locked when calling this */ | ||
| 493 | static void msi2500_isoc_cleanup(struct msi2500_state *s) | ||
| 494 | { | ||
| 495 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 496 | |||
| 497 | msi2500_iso_stop(s); | ||
| 498 | msi2500_iso_free(s); | ||
| 499 | } | ||
| 500 | |||
| 501 | /* Both v4l2_lock and vb_queue_lock should be locked when calling this */ | ||
| 502 | static int msi2500_isoc_init(struct msi2500_state *s) | ||
| 503 | { | ||
| 504 | struct usb_device *udev; | ||
| 505 | struct urb *urb; | ||
| 506 | int i, j, ret; | ||
| 507 | |||
| 508 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 509 | |||
| 510 | s->isoc_errors = 0; | ||
| 511 | udev = s->udev; | ||
| 512 | |||
| 513 | ret = usb_set_interface(s->udev, 0, 1); | ||
| 514 | if (ret) | ||
| 515 | return ret; | ||
| 516 | |||
| 517 | /* Allocate and init Isochronuous urbs */ | ||
| 518 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 519 | urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); | ||
| 520 | if (urb == NULL) { | ||
| 521 | dev_err(&s->udev->dev, | ||
| 522 | "Failed to allocate urb %d\n", i); | ||
| 523 | msi2500_isoc_cleanup(s); | ||
| 524 | return -ENOMEM; | ||
| 525 | } | ||
| 526 | s->urbs[i] = urb; | ||
| 527 | dev_dbg(&s->udev->dev, "Allocated URB at 0x%p\n", urb); | ||
| 528 | |||
| 529 | urb->interval = 1; | ||
| 530 | urb->dev = udev; | ||
| 531 | urb->pipe = usb_rcvisocpipe(udev, 0x81); | ||
| 532 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
| 533 | urb->transfer_buffer = usb_alloc_coherent(udev, ISO_BUFFER_SIZE, | ||
| 534 | GFP_KERNEL, &urb->transfer_dma); | ||
| 535 | if (urb->transfer_buffer == NULL) { | ||
| 536 | dev_err(&s->udev->dev, | ||
| 537 | "Failed to allocate urb buffer %d\n", | ||
| 538 | i); | ||
| 539 | msi2500_isoc_cleanup(s); | ||
| 540 | return -ENOMEM; | ||
| 541 | } | ||
| 542 | urb->transfer_buffer_length = ISO_BUFFER_SIZE; | ||
| 543 | urb->complete = msi2500_isoc_handler; | ||
| 544 | urb->context = s; | ||
| 545 | urb->start_frame = 0; | ||
| 546 | urb->number_of_packets = ISO_FRAMES_PER_DESC; | ||
| 547 | for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { | ||
| 548 | urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; | ||
| 549 | urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | /* link */ | ||
| 554 | for (i = 0; i < MAX_ISO_BUFS; i++) { | ||
| 555 | ret = usb_submit_urb(s->urbs[i], GFP_KERNEL); | ||
| 556 | if (ret) { | ||
| 557 | dev_err(&s->udev->dev, | ||
| 558 | "isoc_init() submit_urb %d failed with error %d\n", | ||
| 559 | i, ret); | ||
| 560 | msi2500_isoc_cleanup(s); | ||
| 561 | return ret; | ||
| 562 | } | ||
| 563 | dev_dbg(&s->udev->dev, "URB 0x%p submitted.\n", s->urbs[i]); | ||
| 564 | } | ||
| 565 | |||
| 566 | /* All is done... */ | ||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | /* Must be called with vb_queue_lock hold */ | ||
| 571 | static void msi2500_cleanup_queued_bufs(struct msi2500_state *s) | ||
| 572 | { | ||
| 573 | unsigned long flags = 0; | ||
| 574 | |||
| 575 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 576 | |||
| 577 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 578 | while (!list_empty(&s->queued_bufs)) { | ||
| 579 | struct msi2500_frame_buf *buf; | ||
| 580 | |||
| 581 | buf = list_entry(s->queued_bufs.next, struct msi2500_frame_buf, | ||
| 582 | list); | ||
| 583 | list_del(&buf->list); | ||
| 584 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
| 585 | } | ||
| 586 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 587 | } | ||
| 588 | |||
| 589 | /* The user yanked out the cable... */ | ||
| 590 | static void msi2500_disconnect(struct usb_interface *intf) | ||
| 591 | { | ||
| 592 | struct v4l2_device *v = usb_get_intfdata(intf); | ||
| 593 | struct msi2500_state *s = | ||
| 594 | container_of(v, struct msi2500_state, v4l2_dev); | ||
| 595 | |||
| 596 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 597 | |||
| 598 | mutex_lock(&s->vb_queue_lock); | ||
| 599 | mutex_lock(&s->v4l2_lock); | ||
| 600 | /* No need to keep the urbs around after disconnection */ | ||
| 601 | s->udev = NULL; | ||
| 602 | v4l2_device_disconnect(&s->v4l2_dev); | ||
| 603 | video_unregister_device(&s->vdev); | ||
| 604 | spi_unregister_master(s->master); | ||
| 605 | mutex_unlock(&s->v4l2_lock); | ||
| 606 | mutex_unlock(&s->vb_queue_lock); | ||
| 607 | |||
| 608 | v4l2_device_put(&s->v4l2_dev); | ||
| 609 | } | ||
| 610 | |||
| 611 | static int msi2500_querycap(struct file *file, void *fh, | ||
| 612 | struct v4l2_capability *cap) | ||
| 613 | { | ||
| 614 | struct msi2500_state *s = video_drvdata(file); | ||
| 615 | |||
| 616 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 617 | |||
| 618 | strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); | ||
| 619 | strlcpy(cap->card, s->vdev.name, sizeof(cap->card)); | ||
| 620 | usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info)); | ||
| 621 | cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING | | ||
| 622 | V4L2_CAP_READWRITE | V4L2_CAP_TUNER; | ||
| 623 | cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; | ||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | |||
| 627 | /* Videobuf2 operations */ | ||
| 628 | static int msi2500_queue_setup(struct vb2_queue *vq, | ||
| 629 | const struct v4l2_format *fmt, unsigned int *nbuffers, | ||
| 630 | unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) | ||
| 631 | { | ||
| 632 | struct msi2500_state *s = vb2_get_drv_priv(vq); | ||
| 633 | |||
| 634 | dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers); | ||
| 635 | |||
| 636 | /* Absolute min and max number of buffers available for mmap() */ | ||
| 637 | *nbuffers = clamp_t(unsigned int, *nbuffers, 8, 32); | ||
| 638 | *nplanes = 1; | ||
| 639 | sizes[0] = PAGE_ALIGN(s->buffersize); | ||
| 640 | dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n", | ||
| 641 | __func__, *nbuffers, sizes[0]); | ||
| 642 | return 0; | ||
| 643 | } | ||
| 644 | |||
| 645 | static void msi2500_buf_queue(struct vb2_buffer *vb) | ||
| 646 | { | ||
| 647 | struct msi2500_state *s = vb2_get_drv_priv(vb->vb2_queue); | ||
| 648 | struct msi2500_frame_buf *buf = | ||
| 649 | container_of(vb, struct msi2500_frame_buf, vb); | ||
| 650 | unsigned long flags = 0; | ||
| 651 | |||
| 652 | /* Check the device has not disconnected between prep and queuing */ | ||
| 653 | if (unlikely(!s->udev)) { | ||
| 654 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
| 655 | return; | ||
| 656 | } | ||
| 657 | |||
| 658 | spin_lock_irqsave(&s->queued_bufs_lock, flags); | ||
| 659 | list_add_tail(&buf->list, &s->queued_bufs); | ||
| 660 | spin_unlock_irqrestore(&s->queued_bufs_lock, flags); | ||
| 661 | } | ||
| 662 | |||
| 663 | #define CMD_WREG 0x41 | ||
| 664 | #define CMD_START_STREAMING 0x43 | ||
| 665 | #define CMD_STOP_STREAMING 0x45 | ||
| 666 | #define CMD_READ_UNKNOW 0x48 | ||
| 667 | |||
| 668 | #define msi2500_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \ | ||
| 669 | char *_direction; \ | ||
| 670 | if (_t & USB_DIR_IN) \ | ||
| 671 | _direction = "<<<"; \ | ||
| 672 | else \ | ||
| 673 | _direction = ">>>"; \ | ||
| 674 | dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \ | ||
| 675 | "%s %*ph\n", __func__, _t, _r, _v & 0xff, _v >> 8, \ | ||
| 676 | _i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \ | ||
| 677 | _l, _b); \ | ||
| 678 | } | ||
| 679 | |||
| 680 | static int msi2500_ctrl_msg(struct msi2500_state *s, u8 cmd, u32 data) | ||
| 681 | { | ||
| 682 | int ret; | ||
| 683 | u8 request = cmd; | ||
| 684 | u8 requesttype = USB_DIR_OUT | USB_TYPE_VENDOR; | ||
| 685 | u16 value = (data >> 0) & 0xffff; | ||
| 686 | u16 index = (data >> 16) & 0xffff; | ||
| 687 | |||
| 688 | msi2500_dbg_usb_control_msg(s->udev, | ||
| 689 | request, requesttype, value, index, NULL, 0); | ||
| 690 | |||
| 691 | ret = usb_control_msg(s->udev, usb_sndctrlpipe(s->udev, 0), | ||
| 692 | request, requesttype, value, index, NULL, 0, 2000); | ||
| 693 | |||
| 694 | if (ret) | ||
| 695 | dev_err(&s->udev->dev, "%s: failed %d, cmd %02x, data %04x\n", | ||
| 696 | __func__, ret, cmd, data); | ||
| 697 | |||
| 698 | return ret; | ||
| 699 | }; | ||
| 700 | |||
| 701 | #define F_REF 24000000 | ||
| 702 | #define DIV_R_IN 2 | ||
| 703 | static int msi2500_set_usb_adc(struct msi2500_state *s) | ||
| 704 | { | ||
| 705 | int ret, div_n, div_m, div_r_out, f_sr, f_vco, fract; | ||
| 706 | u32 reg3, reg4, reg7; | ||
| 707 | struct v4l2_ctrl *bandwidth_auto; | ||
| 708 | struct v4l2_ctrl *bandwidth; | ||
| 709 | |||
| 710 | f_sr = s->f_adc; | ||
| 711 | |||
| 712 | /* set tuner, subdev, filters according to sampling rate */ | ||
| 713 | bandwidth_auto = v4l2_ctrl_find(&s->hdl, | ||
| 714 | V4L2_CID_RF_TUNER_BANDWIDTH_AUTO); | ||
| 715 | if (v4l2_ctrl_g_ctrl(bandwidth_auto)) { | ||
| 716 | bandwidth = v4l2_ctrl_find(&s->hdl, | ||
| 717 | V4L2_CID_RF_TUNER_BANDWIDTH); | ||
| 718 | v4l2_ctrl_s_ctrl(bandwidth, s->f_adc); | ||
| 719 | } | ||
| 720 | |||
| 721 | /* select stream format */ | ||
| 722 | switch (s->pixelformat) { | ||
| 723 | case V4L2_SDR_FMT_CU8: | ||
| 724 | reg7 = 0x000c9407; /* 504 */ | ||
| 725 | break; | ||
| 726 | case V4L2_SDR_FMT_CU16LE: | ||
| 727 | reg7 = 0x00009407; /* 252 */ | ||
| 728 | break; | ||
| 729 | case V4L2_SDR_FMT_CS8: | ||
| 730 | reg7 = 0x000c9407; /* 504 */ | ||
| 731 | break; | ||
| 732 | case MSI2500_PIX_FMT_SDR_MSI2500_384: | ||
| 733 | reg7 = 0x0000a507; /* 384 */ | ||
| 734 | break; | ||
| 735 | case MSI2500_PIX_FMT_SDR_S12: | ||
| 736 | reg7 = 0x00008507; /* 336 */ | ||
| 737 | break; | ||
| 738 | case V4L2_SDR_FMT_CS14LE: | ||
| 739 | reg7 = 0x00009407; /* 252 */ | ||
| 740 | break; | ||
| 741 | default: | ||
| 742 | reg7 = 0x000c9407; /* 504 */ | ||
| 743 | break; | ||
| 744 | } | ||
| 745 | |||
| 746 | /* | ||
| 747 | * Synthesizer config is just a educated guess... | ||
| 748 | * | ||
| 749 | * [7:0] 0x03, register address | ||
| 750 | * [8] 1, power control | ||
| 751 | * [9] ?, power control | ||
| 752 | * [12:10] output divider | ||
| 753 | * [13] 0 ? | ||
| 754 | * [14] 0 ? | ||
| 755 | * [15] fractional MSB, bit 20 | ||
| 756 | * [16:19] N | ||
| 757 | * [23:20] ? | ||
| 758 | * [24:31] 0x01 | ||
| 759 | * | ||
| 760 | * output divider | ||
| 761 | * val div | ||
| 762 | * 0 - (invalid) | ||
| 763 | * 1 4 | ||
| 764 | * 2 6 | ||
| 765 | * 3 8 | ||
| 766 | * 4 10 | ||
| 767 | * 5 12 | ||
| 768 | * 6 14 | ||
| 769 | * 7 16 | ||
| 770 | * | ||
| 771 | * VCO 202000000 - 720000000++ | ||
| 772 | */ | ||
| 773 | reg3 = 0x01000303; | ||
| 774 | reg4 = 0x00000004; | ||
| 775 | |||
| 776 | /* XXX: Filters? AGC? */ | ||
| 777 | if (f_sr < 6000000) | ||
| 778 | reg3 |= 0x1 << 20; | ||
| 779 | else if (f_sr < 7000000) | ||
| 780 | reg3 |= 0x5 << 20; | ||
| 781 | else if (f_sr < 8500000) | ||
| 782 | reg3 |= 0x9 << 20; | ||
| 783 | else | ||
| 784 | reg3 |= 0xd << 20; | ||
| 785 | |||
| 786 | for (div_r_out = 4; div_r_out < 16; div_r_out += 2) { | ||
| 787 | f_vco = f_sr * div_r_out * 12; | ||
| 788 | dev_dbg(&s->udev->dev, "%s: div_r_out=%d f_vco=%d\n", | ||
| 789 | __func__, div_r_out, f_vco); | ||
| 790 | if (f_vco >= 202000000) | ||
| 791 | break; | ||
| 792 | } | ||
| 793 | |||
| 794 | div_n = f_vco / (F_REF * DIV_R_IN); | ||
| 795 | div_m = f_vco % (F_REF * DIV_R_IN); | ||
| 796 | fract = 0x200000ul * div_m / (F_REF * DIV_R_IN); | ||
| 797 | |||
| 798 | reg3 |= div_n << 16; | ||
| 799 | reg3 |= (div_r_out / 2 - 1) << 10; | ||
| 800 | reg3 |= ((fract >> 20) & 0x000001) << 15; /* [20] */ | ||
| 801 | reg4 |= ((fract >> 0) & 0x0fffff) << 8; /* [19:0] */ | ||
| 802 | |||
| 803 | dev_dbg(&s->udev->dev, | ||
| 804 | "%s: f_sr=%d f_vco=%d div_n=%d div_m=%d div_r_out=%d reg3=%08x reg4=%08x\n", | ||
| 805 | __func__, f_sr, f_vco, div_n, div_m, div_r_out, reg3, | ||
| 806 | reg4); | ||
| 807 | |||
| 808 | ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00608008); | ||
| 809 | if (ret) | ||
| 810 | goto err; | ||
| 811 | |||
| 812 | ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00000c05); | ||
| 813 | if (ret) | ||
| 814 | goto err; | ||
| 815 | |||
| 816 | ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00020000); | ||
| 817 | if (ret) | ||
| 818 | goto err; | ||
| 819 | |||
| 820 | ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00480102); | ||
| 821 | if (ret) | ||
| 822 | goto err; | ||
| 823 | |||
| 824 | ret = msi2500_ctrl_msg(s, CMD_WREG, 0x00f38008); | ||
| 825 | if (ret) | ||
| 826 | goto err; | ||
| 827 | |||
| 828 | ret = msi2500_ctrl_msg(s, CMD_WREG, reg7); | ||
| 829 | if (ret) | ||
| 830 | goto err; | ||
| 831 | |||
| 832 | ret = msi2500_ctrl_msg(s, CMD_WREG, reg4); | ||
| 833 | if (ret) | ||
| 834 | goto err; | ||
| 835 | |||
| 836 | ret = msi2500_ctrl_msg(s, CMD_WREG, reg3); | ||
| 837 | if (ret) | ||
| 838 | goto err; | ||
| 839 | err: | ||
| 840 | return ret; | ||
| 841 | }; | ||
| 842 | |||
| 843 | static int msi2500_start_streaming(struct vb2_queue *vq, unsigned int count) | ||
| 844 | { | ||
| 845 | struct msi2500_state *s = vb2_get_drv_priv(vq); | ||
| 846 | int ret; | ||
| 847 | |||
| 848 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 849 | |||
| 850 | if (!s->udev) | ||
| 851 | return -ENODEV; | ||
| 852 | |||
| 853 | if (mutex_lock_interruptible(&s->v4l2_lock)) | ||
| 854 | return -ERESTARTSYS; | ||
| 855 | |||
| 856 | /* wake-up tuner */ | ||
| 857 | v4l2_subdev_call(s->v4l2_subdev, core, s_power, 1); | ||
| 858 | |||
| 859 | ret = msi2500_set_usb_adc(s); | ||
| 860 | |||
| 861 | ret = msi2500_isoc_init(s); | ||
| 862 | if (ret) | ||
| 863 | msi2500_cleanup_queued_bufs(s); | ||
| 864 | |||
| 865 | ret = msi2500_ctrl_msg(s, CMD_START_STREAMING, 0); | ||
| 866 | |||
| 867 | mutex_unlock(&s->v4l2_lock); | ||
| 868 | |||
| 869 | return ret; | ||
| 870 | } | ||
| 871 | |||
| 872 | static void msi2500_stop_streaming(struct vb2_queue *vq) | ||
| 873 | { | ||
| 874 | struct msi2500_state *s = vb2_get_drv_priv(vq); | ||
| 875 | |||
| 876 | dev_dbg(&s->udev->dev, "%s:\n", __func__); | ||
| 877 | |||
| 878 | mutex_lock(&s->v4l2_lock); | ||
| 879 | |||
| 880 | if (s->udev) | ||
| 881 | msi2500_isoc_cleanup(s); | ||
| 882 | |||
| 883 | msi2500_cleanup_queued_bufs(s); | ||
| 884 | |||
| 885 | /* according to tests, at least 700us delay is required */ | ||
| 886 | msleep(20); | ||
| 887 | if (!msi2500_ctrl_msg(s, CMD_STOP_STREAMING, 0)) { | ||
| 888 | /* sleep USB IF / ADC */ | ||
| 889 | msi2500_ctrl_msg(s, CMD_WREG, 0x01000003); | ||
| 890 | } | ||
| 891 | |||
| 892 | /* sleep tuner */ | ||
| 893 | v4l2_subdev_call(s->v4l2_subdev, core, s_power, 0); | ||
| 894 | |||
| 895 | mutex_unlock(&s->v4l2_lock); | ||
| 896 | } | ||
| 897 | |||
| 898 | static struct vb2_ops msi2500_vb2_ops = { | ||
| 899 | .queue_setup = msi2500_queue_setup, | ||
| 900 | .buf_queue = msi2500_buf_queue, | ||
| 901 | .start_streaming = msi2500_start_streaming, | ||
| 902 | .stop_streaming = msi2500_stop_streaming, | ||
| 903 | .wait_prepare = vb2_ops_wait_prepare, | ||
| 904 | .wait_finish = vb2_ops_wait_finish, | ||
| 905 | }; | ||
| 906 | |||
| 907 | static int msi2500_enum_fmt_sdr_cap(struct file *file, void *priv, | ||
| 908 | struct v4l2_fmtdesc *f) | ||
| 909 | { | ||
| 910 | struct msi2500_state *s = video_drvdata(file); | ||
| 911 | |||
| 912 | dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index); | ||
| 913 | |||
| 914 | if (f->index >= s->num_formats) | ||
| 915 | return -EINVAL; | ||
| 916 | |||
| 917 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); | ||
| 918 | f->pixelformat = formats[f->index].pixelformat; | ||
| 919 | |||
| 920 | return 0; | ||
| 921 | } | ||
| 922 | |||
| 923 | static int msi2500_g_fmt_sdr_cap(struct file *file, void *priv, | ||
| 924 | struct v4l2_format *f) | ||
| 925 | { | ||
| 926 | struct msi2500_state *s = video_drvdata(file); | ||
| 927 | |||
| 928 | dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | ||
| 929 | (char *)&s->pixelformat); | ||
| 930 | |||
| 931 | f->fmt.sdr.pixelformat = s->pixelformat; | ||
| 932 | f->fmt.sdr.buffersize = s->buffersize; | ||
| 933 | memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||
| 934 | |||
| 935 | return 0; | ||
| 936 | } | ||
| 937 | |||
| 938 | static int msi2500_s_fmt_sdr_cap(struct file *file, void *priv, | ||
| 939 | struct v4l2_format *f) | ||
| 940 | { | ||
| 941 | struct msi2500_state *s = video_drvdata(file); | ||
| 942 | struct vb2_queue *q = &s->vb_queue; | ||
| 943 | int i; | ||
| 944 | |||
| 945 | dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | ||
| 946 | (char *)&f->fmt.sdr.pixelformat); | ||
| 947 | |||
| 948 | if (vb2_is_busy(q)) | ||
| 949 | return -EBUSY; | ||
| 950 | |||
| 951 | memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||
| 952 | for (i = 0; i < s->num_formats; i++) { | ||
| 953 | if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { | ||
| 954 | s->pixelformat = formats[i].pixelformat; | ||
| 955 | s->buffersize = formats[i].buffersize; | ||
| 956 | f->fmt.sdr.buffersize = formats[i].buffersize; | ||
| 957 | return 0; | ||
| 958 | } | ||
| 959 | } | ||
| 960 | |||
| 961 | s->pixelformat = formats[0].pixelformat; | ||
| 962 | s->buffersize = formats[0].buffersize; | ||
| 963 | f->fmt.sdr.pixelformat = formats[0].pixelformat; | ||
| 964 | f->fmt.sdr.buffersize = formats[0].buffersize; | ||
| 965 | |||
| 966 | return 0; | ||
| 967 | } | ||
| 968 | |||
| 969 | static int msi2500_try_fmt_sdr_cap(struct file *file, void *priv, | ||
| 970 | struct v4l2_format *f) | ||
| 971 | { | ||
| 972 | struct msi2500_state *s = video_drvdata(file); | ||
| 973 | int i; | ||
| 974 | |||
| 975 | dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__, | ||
| 976 | (char *)&f->fmt.sdr.pixelformat); | ||
| 977 | |||
| 978 | memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved)); | ||
| 979 | for (i = 0; i < s->num_formats; i++) { | ||
| 980 | if (formats[i].pixelformat == f->fmt.sdr.pixelformat) { | ||
| 981 | f->fmt.sdr.buffersize = formats[i].buffersize; | ||
| 982 | return 0; | ||
| 983 | } | ||
| 984 | } | ||
| 985 | |||
| 986 | f->fmt.sdr.pixelformat = formats[0].pixelformat; | ||
| 987 | f->fmt.sdr.buffersize = formats[0].buffersize; | ||
| 988 | |||
| 989 | return 0; | ||
| 990 | } | ||
| 991 | |||
| 992 | static int msi2500_s_tuner(struct file *file, void *priv, | ||
| 993 | const struct v4l2_tuner *v) | ||
| 994 | { | ||
| 995 | struct msi2500_state *s = video_drvdata(file); | ||
| 996 | int ret; | ||
| 997 | |||
| 998 | dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index); | ||
| 999 | |||
| 1000 | if (v->index == 0) | ||
| 1001 | ret = 0; | ||
| 1002 | else if (v->index == 1) | ||
| 1003 | ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_tuner, v); | ||
| 1004 | else | ||
| 1005 | ret = -EINVAL; | ||
| 1006 | |||
| 1007 | return ret; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | static int msi2500_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v) | ||
| 1011 | { | ||
| 1012 | struct msi2500_state *s = video_drvdata(file); | ||
| 1013 | int ret; | ||
| 1014 | |||
| 1015 | dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index); | ||
| 1016 | |||
| 1017 | if (v->index == 0) { | ||
| 1018 | strlcpy(v->name, "Mirics MSi2500", sizeof(v->name)); | ||
| 1019 | v->type = V4L2_TUNER_ADC; | ||
| 1020 | v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS; | ||
| 1021 | v->rangelow = 1200000; | ||
| 1022 | v->rangehigh = 15000000; | ||
| 1023 | ret = 0; | ||
| 1024 | } else if (v->index == 1) { | ||
| 1025 | ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_tuner, v); | ||
| 1026 | } else { | ||
| 1027 | ret = -EINVAL; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | return ret; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | static int msi2500_g_frequency(struct file *file, void *priv, | ||
| 1034 | struct v4l2_frequency *f) | ||
| 1035 | { | ||
| 1036 | struct msi2500_state *s = video_drvdata(file); | ||
| 1037 | int ret = 0; | ||
| 1038 | |||
| 1039 | dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n", | ||
| 1040 | __func__, f->tuner, f->type); | ||
| 1041 | |||
| 1042 | if (f->tuner == 0) { | ||
| 1043 | f->frequency = s->f_adc; | ||
| 1044 | ret = 0; | ||
| 1045 | } else if (f->tuner == 1) { | ||
| 1046 | f->type = V4L2_TUNER_RF; | ||
| 1047 | ret = v4l2_subdev_call(s->v4l2_subdev, tuner, g_frequency, f); | ||
| 1048 | } else { | ||
| 1049 | ret = -EINVAL; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | return ret; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static int msi2500_s_frequency(struct file *file, void *priv, | ||
| 1056 | const struct v4l2_frequency *f) | ||
| 1057 | { | ||
| 1058 | struct msi2500_state *s = video_drvdata(file); | ||
| 1059 | int ret; | ||
| 1060 | |||
| 1061 | dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n", | ||
| 1062 | __func__, f->tuner, f->type, f->frequency); | ||
| 1063 | |||
| 1064 | if (f->tuner == 0) { | ||
| 1065 | s->f_adc = clamp_t(unsigned int, f->frequency, | ||
| 1066 | bands[0].rangelow, | ||
| 1067 | bands[0].rangehigh); | ||
| 1068 | dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n", | ||
| 1069 | __func__, s->f_adc); | ||
| 1070 | ret = msi2500_set_usb_adc(s); | ||
| 1071 | } else if (f->tuner == 1) { | ||
| 1072 | ret = v4l2_subdev_call(s->v4l2_subdev, tuner, s_frequency, f); | ||
| 1073 | } else { | ||
| 1074 | ret = -EINVAL; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | return ret; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | static int msi2500_enum_freq_bands(struct file *file, void *priv, | ||
| 1081 | struct v4l2_frequency_band *band) | ||
| 1082 | { | ||
| 1083 | struct msi2500_state *s = video_drvdata(file); | ||
| 1084 | int ret; | ||
| 1085 | |||
| 1086 | dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n", | ||
| 1087 | __func__, band->tuner, band->type, band->index); | ||
| 1088 | |||
| 1089 | if (band->tuner == 0) { | ||
| 1090 | if (band->index >= ARRAY_SIZE(bands)) { | ||
| 1091 | ret = -EINVAL; | ||
| 1092 | } else { | ||
| 1093 | *band = bands[band->index]; | ||
| 1094 | ret = 0; | ||
| 1095 | } | ||
| 1096 | } else if (band->tuner == 1) { | ||
| 1097 | ret = v4l2_subdev_call(s->v4l2_subdev, tuner, | ||
| 1098 | enum_freq_bands, band); | ||
| 1099 | } else { | ||
| 1100 | ret = -EINVAL; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | return ret; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | static const struct v4l2_ioctl_ops msi2500_ioctl_ops = { | ||
| 1107 | .vidioc_querycap = msi2500_querycap, | ||
| 1108 | |||
| 1109 | .vidioc_enum_fmt_sdr_cap = msi2500_enum_fmt_sdr_cap, | ||
| 1110 | .vidioc_g_fmt_sdr_cap = msi2500_g_fmt_sdr_cap, | ||
| 1111 | .vidioc_s_fmt_sdr_cap = msi2500_s_fmt_sdr_cap, | ||
| 1112 | .vidioc_try_fmt_sdr_cap = msi2500_try_fmt_sdr_cap, | ||
| 1113 | |||
| 1114 | .vidioc_reqbufs = vb2_ioctl_reqbufs, | ||
| 1115 | .vidioc_create_bufs = vb2_ioctl_create_bufs, | ||
| 1116 | .vidioc_prepare_buf = vb2_ioctl_prepare_buf, | ||
| 1117 | .vidioc_querybuf = vb2_ioctl_querybuf, | ||
| 1118 | .vidioc_qbuf = vb2_ioctl_qbuf, | ||
| 1119 | .vidioc_dqbuf = vb2_ioctl_dqbuf, | ||
| 1120 | |||
| 1121 | .vidioc_streamon = vb2_ioctl_streamon, | ||
| 1122 | .vidioc_streamoff = vb2_ioctl_streamoff, | ||
| 1123 | |||
| 1124 | .vidioc_g_tuner = msi2500_g_tuner, | ||
| 1125 | .vidioc_s_tuner = msi2500_s_tuner, | ||
| 1126 | |||
| 1127 | .vidioc_g_frequency = msi2500_g_frequency, | ||
| 1128 | .vidioc_s_frequency = msi2500_s_frequency, | ||
| 1129 | .vidioc_enum_freq_bands = msi2500_enum_freq_bands, | ||
| 1130 | |||
| 1131 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, | ||
| 1132 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, | ||
| 1133 | .vidioc_log_status = v4l2_ctrl_log_status, | ||
| 1134 | }; | ||
| 1135 | |||
| 1136 | static const struct v4l2_file_operations msi2500_fops = { | ||
| 1137 | .owner = THIS_MODULE, | ||
| 1138 | .open = v4l2_fh_open, | ||
| 1139 | .release = vb2_fop_release, | ||
| 1140 | .read = vb2_fop_read, | ||
| 1141 | .poll = vb2_fop_poll, | ||
| 1142 | .mmap = vb2_fop_mmap, | ||
| 1143 | .unlocked_ioctl = video_ioctl2, | ||
| 1144 | }; | ||
| 1145 | |||
| 1146 | static struct video_device msi2500_template = { | ||
| 1147 | .name = "Mirics MSi3101 SDR Dongle", | ||
| 1148 | .release = video_device_release_empty, | ||
| 1149 | .fops = &msi2500_fops, | ||
| 1150 | .ioctl_ops = &msi2500_ioctl_ops, | ||
| 1151 | }; | ||
| 1152 | |||
| 1153 | static void msi2500_video_release(struct v4l2_device *v) | ||
| 1154 | { | ||
| 1155 | struct msi2500_state *s = | ||
| 1156 | container_of(v, struct msi2500_state, v4l2_dev); | ||
| 1157 | |||
| 1158 | v4l2_ctrl_handler_free(&s->hdl); | ||
| 1159 | v4l2_device_unregister(&s->v4l2_dev); | ||
| 1160 | kfree(s); | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | static int msi2500_transfer_one_message(struct spi_master *master, | ||
| 1164 | struct spi_message *m) | ||
| 1165 | { | ||
| 1166 | struct msi2500_state *s = spi_master_get_devdata(master); | ||
| 1167 | struct spi_transfer *t; | ||
| 1168 | int ret = 0; | ||
| 1169 | u32 data; | ||
| 1170 | |||
| 1171 | list_for_each_entry(t, &m->transfers, transfer_list) { | ||
| 1172 | dev_dbg(&s->udev->dev, "%s: msg=%*ph\n", | ||
| 1173 | __func__, t->len, t->tx_buf); | ||
| 1174 | data = 0x09; /* reg 9 is SPI adapter */ | ||
| 1175 | data |= ((u8 *)t->tx_buf)[0] << 8; | ||
| 1176 | data |= ((u8 *)t->tx_buf)[1] << 16; | ||
| 1177 | data |= ((u8 *)t->tx_buf)[2] << 24; | ||
| 1178 | ret = msi2500_ctrl_msg(s, CMD_WREG, data); | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | m->status = ret; | ||
| 1182 | spi_finalize_current_message(master); | ||
| 1183 | return ret; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | static int msi2500_probe(struct usb_interface *intf, | ||
| 1187 | const struct usb_device_id *id) | ||
| 1188 | { | ||
| 1189 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1190 | struct msi2500_state *s = NULL; | ||
| 1191 | struct v4l2_subdev *sd; | ||
| 1192 | struct spi_master *master; | ||
| 1193 | int ret; | ||
| 1194 | static struct spi_board_info board_info = { | ||
| 1195 | .modalias = "msi001", | ||
| 1196 | .bus_num = 0, | ||
| 1197 | .chip_select = 0, | ||
| 1198 | .max_speed_hz = 12000000, | ||
| 1199 | }; | ||
| 1200 | |||
| 1201 | s = kzalloc(sizeof(struct msi2500_state), GFP_KERNEL); | ||
| 1202 | if (s == NULL) { | ||
| 1203 | pr_err("Could not allocate memory for msi2500_state\n"); | ||
| 1204 | return -ENOMEM; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | mutex_init(&s->v4l2_lock); | ||
| 1208 | mutex_init(&s->vb_queue_lock); | ||
| 1209 | spin_lock_init(&s->queued_bufs_lock); | ||
| 1210 | INIT_LIST_HEAD(&s->queued_bufs); | ||
| 1211 | s->udev = udev; | ||
| 1212 | s->f_adc = bands[0].rangelow; | ||
| 1213 | s->pixelformat = formats[0].pixelformat; | ||
| 1214 | s->buffersize = formats[0].buffersize; | ||
| 1215 | s->num_formats = NUM_FORMATS; | ||
| 1216 | if (msi2500_emulated_fmt == false) | ||
| 1217 | s->num_formats -= 2; | ||
| 1218 | |||
| 1219 | /* Init videobuf2 queue structure */ | ||
| 1220 | s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE; | ||
| 1221 | s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; | ||
| 1222 | s->vb_queue.drv_priv = s; | ||
| 1223 | s->vb_queue.buf_struct_size = sizeof(struct msi2500_frame_buf); | ||
| 1224 | s->vb_queue.ops = &msi2500_vb2_ops; | ||
| 1225 | s->vb_queue.mem_ops = &vb2_vmalloc_memops; | ||
| 1226 | s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
| 1227 | ret = vb2_queue_init(&s->vb_queue); | ||
| 1228 | if (ret) { | ||
| 1229 | dev_err(&s->udev->dev, "Could not initialize vb2 queue\n"); | ||
| 1230 | goto err_free_mem; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | /* Init video_device structure */ | ||
| 1234 | s->vdev = msi2500_template; | ||
| 1235 | s->vdev.queue = &s->vb_queue; | ||
| 1236 | s->vdev.queue->lock = &s->vb_queue_lock; | ||
| 1237 | video_set_drvdata(&s->vdev, s); | ||
| 1238 | |||
| 1239 | /* Register the v4l2_device structure */ | ||
| 1240 | s->v4l2_dev.release = msi2500_video_release; | ||
| 1241 | ret = v4l2_device_register(&intf->dev, &s->v4l2_dev); | ||
| 1242 | if (ret) { | ||
| 1243 | dev_err(&s->udev->dev, | ||
| 1244 | "Failed to register v4l2-device (%d)\n", ret); | ||
| 1245 | goto err_free_mem; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | /* SPI master adapter */ | ||
| 1249 | master = spi_alloc_master(&s->udev->dev, 0); | ||
| 1250 | if (master == NULL) { | ||
| 1251 | ret = -ENOMEM; | ||
| 1252 | goto err_unregister_v4l2_dev; | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | s->master = master; | ||
| 1256 | master->bus_num = 0; | ||
| 1257 | master->num_chipselect = 1; | ||
| 1258 | master->transfer_one_message = msi2500_transfer_one_message; | ||
| 1259 | spi_master_set_devdata(master, s); | ||
| 1260 | ret = spi_register_master(master); | ||
| 1261 | if (ret) { | ||
| 1262 | spi_master_put(master); | ||
| 1263 | goto err_unregister_v4l2_dev; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | /* load v4l2 subdevice */ | ||
| 1267 | sd = v4l2_spi_new_subdev(&s->v4l2_dev, master, &board_info); | ||
| 1268 | s->v4l2_subdev = sd; | ||
| 1269 | if (sd == NULL) { | ||
| 1270 | dev_err(&s->udev->dev, "cannot get v4l2 subdevice\n"); | ||
| 1271 | ret = -ENODEV; | ||
| 1272 | goto err_unregister_master; | ||
| 1273 | } | ||
| 1274 | |||
| 1275 | /* Register controls */ | ||
| 1276 | v4l2_ctrl_handler_init(&s->hdl, 0); | ||
| 1277 | if (s->hdl.error) { | ||
| 1278 | ret = s->hdl.error; | ||
| 1279 | dev_err(&s->udev->dev, "Could not initialize controls\n"); | ||
| 1280 | goto err_free_controls; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | /* currently all controls are from subdev */ | ||
| 1284 | v4l2_ctrl_add_handler(&s->hdl, sd->ctrl_handler, NULL); | ||
| 1285 | |||
| 1286 | s->v4l2_dev.ctrl_handler = &s->hdl; | ||
| 1287 | s->vdev.v4l2_dev = &s->v4l2_dev; | ||
| 1288 | s->vdev.lock = &s->v4l2_lock; | ||
| 1289 | |||
| 1290 | ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1); | ||
| 1291 | if (ret) { | ||
| 1292 | dev_err(&s->udev->dev, | ||
| 1293 | "Failed to register as video device (%d)\n", | ||
| 1294 | ret); | ||
| 1295 | goto err_unregister_v4l2_dev; | ||
| 1296 | } | ||
| 1297 | dev_info(&s->udev->dev, "Registered as %s\n", | ||
| 1298 | video_device_node_name(&s->vdev)); | ||
| 1299 | dev_notice(&s->udev->dev, | ||
| 1300 | "%s: SDR API is still slightly experimental and functionality changes may follow\n", | ||
| 1301 | KBUILD_MODNAME); | ||
| 1302 | |||
| 1303 | return 0; | ||
| 1304 | |||
| 1305 | err_free_controls: | ||
| 1306 | v4l2_ctrl_handler_free(&s->hdl); | ||
| 1307 | err_unregister_master: | ||
| 1308 | spi_unregister_master(s->master); | ||
| 1309 | err_unregister_v4l2_dev: | ||
| 1310 | v4l2_device_unregister(&s->v4l2_dev); | ||
| 1311 | err_free_mem: | ||
| 1312 | kfree(s); | ||
| 1313 | return ret; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | /* USB device ID list */ | ||
| 1317 | static struct usb_device_id msi2500_id_table[] = { | ||
| 1318 | { USB_DEVICE(0x1df7, 0x2500) }, /* Mirics MSi3101 SDR Dongle */ | ||
| 1319 | { USB_DEVICE(0x2040, 0xd300) }, /* Hauppauge WinTV 133559 LF */ | ||
| 1320 | { } | ||
| 1321 | }; | ||
| 1322 | MODULE_DEVICE_TABLE(usb, msi2500_id_table); | ||
| 1323 | |||
| 1324 | /* USB subsystem interface */ | ||
| 1325 | static struct usb_driver msi2500_driver = { | ||
| 1326 | .name = KBUILD_MODNAME, | ||
| 1327 | .probe = msi2500_probe, | ||
| 1328 | .disconnect = msi2500_disconnect, | ||
| 1329 | .id_table = msi2500_id_table, | ||
| 1330 | }; | ||
| 1331 | |||
| 1332 | module_usb_driver(msi2500_driver); | ||
| 1333 | |||
| 1334 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
| 1335 | MODULE_DESCRIPTION("Mirics MSi3101 SDR Dongle"); | ||
| 1336 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c index 7c280f35eea9..1b158f1167ed 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c | |||
| @@ -951,15 +951,9 @@ static long pvr2_v4l2_ioctl(struct file *file, | |||
| 951 | if (ret < 0) { | 951 | if (ret < 0) { |
| 952 | if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { | 952 | if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { |
| 953 | pvr2_trace(PVR2_TRACE_V4LIOCTL, | 953 | pvr2_trace(PVR2_TRACE_V4LIOCTL, |
| 954 | "pvr2_v4l2_do_ioctl failure, ret=%ld", ret); | 954 | "pvr2_v4l2_do_ioctl failure, ret=%ld" |
| 955 | } else { | 955 | " command was:", ret); |
| 956 | if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { | 956 | v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd); |
| 957 | pvr2_trace(PVR2_TRACE_V4LIOCTL, | ||
| 958 | "pvr2_v4l2_do_ioctl failure, ret=%ld" | ||
| 959 | " command was:", ret); | ||
| 960 | v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), | ||
| 961 | cmd); | ||
| 962 | } | ||
| 963 | } | 957 | } |
| 964 | } else { | 958 | } else { |
| 965 | pvr2_trace(PVR2_TRACE_V4LIOCTL, | 959 | pvr2_trace(PVR2_TRACE_V4LIOCTL, |
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index a73b0bced96f..15b754da4a2c 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c | |||
| @@ -1013,7 +1013,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
| 1013 | strcpy(pdev->vdev.name, name); | 1013 | strcpy(pdev->vdev.name, name); |
| 1014 | pdev->vdev.queue = &pdev->vb_queue; | 1014 | pdev->vdev.queue = &pdev->vb_queue; |
| 1015 | pdev->vdev.queue->lock = &pdev->vb_queue_lock; | 1015 | pdev->vdev.queue->lock = &pdev->vb_queue_lock; |
| 1016 | set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags); | ||
| 1017 | video_set_drvdata(&pdev->vdev, pdev); | 1016 | video_set_drvdata(&pdev->vdev, pdev); |
| 1018 | 1017 | ||
| 1019 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); | 1018 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); |
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index a44466bc7b86..2c901861034a 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c | |||
| @@ -1676,7 +1676,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev) | |||
| 1676 | vc->vdev.ctrl_handler = &vc->hdl; | 1676 | vc->vdev.ctrl_handler = &vc->hdl; |
| 1677 | vc->vdev.lock = &dev->lock; | 1677 | vc->vdev.lock = &dev->lock; |
| 1678 | vc->vdev.v4l2_dev = &dev->v4l2_dev; | 1678 | vc->vdev.v4l2_dev = &dev->v4l2_dev; |
| 1679 | set_bit(V4L2_FL_USE_FH_PRIO, &vc->vdev.flags); | ||
| 1680 | video_set_drvdata(&vc->vdev, vc); | 1679 | video_set_drvdata(&vc->vdev, vc); |
| 1681 | if (video_nr == -1) | 1680 | if (video_nr == -1) |
| 1682 | ret = video_register_device(&vc->vdev, | 1681 | ret = video_register_device(&vc->vdev, |
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 5461341a31cb..233054311a62 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c | |||
| @@ -671,7 +671,6 @@ int stk1160_video_register(struct stk1160 *dev) | |||
| 671 | 671 | ||
| 672 | /* This will be used to set video_device parent */ | 672 | /* This will be used to set video_device parent */ |
| 673 | dev->vdev.v4l2_dev = &dev->v4l2_dev; | 673 | dev->vdev.v4l2_dev = &dev->v4l2_dev; |
| 674 | set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags); | ||
| 675 | 674 | ||
| 676 | /* NTSC is default */ | 675 | /* NTSC is default */ |
| 677 | dev->norm = V4L2_STD_NTSC_M; | 676 | dev->norm = V4L2_STD_NTSC_M; |
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index be77482c3070..3588dc38db87 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c | |||
| @@ -923,7 +923,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp, | |||
| 923 | pix_format->bytesperline = 2 * pix_format->width; | 923 | pix_format->bytesperline = 2 * pix_format->width; |
| 924 | pix_format->sizeimage = pix_format->bytesperline | 924 | pix_format->sizeimage = pix_format->bytesperline |
| 925 | * pix_format->height; | 925 | * pix_format->height; |
| 926 | pix_format->priv = 0; | ||
| 927 | return 0; | 926 | return 0; |
| 928 | } | 927 | } |
| 929 | 928 | ||
| @@ -967,7 +966,6 @@ static int stk_try_fmt_vid_cap(struct file *filp, | |||
| 967 | fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width; | 966 | fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width; |
| 968 | fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline | 967 | fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline |
| 969 | * fmtd->fmt.pix.height; | 968 | * fmtd->fmt.pix.height; |
| 970 | fmtd->fmt.pix.priv = 0; | ||
| 971 | return 0; | 969 | return 0; |
| 972 | } | 970 | } |
| 973 | 971 | ||
| @@ -1266,7 +1264,6 @@ static int stk_register_video_device(struct stk_camera *dev) | |||
| 1266 | dev->vdev.lock = &dev->lock; | 1264 | dev->vdev.lock = &dev->lock; |
| 1267 | dev->vdev.debug = debug; | 1265 | dev->vdev.debug = debug; |
| 1268 | dev->vdev.v4l2_dev = &dev->v4l2_dev; | 1266 | dev->vdev.v4l2_dev = &dev->v4l2_dev; |
| 1269 | set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags); | ||
| 1270 | video_set_drvdata(&dev->vdev, dev); | 1267 | video_set_drvdata(&dev->vdev, dev); |
| 1271 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); | 1268 | err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); |
| 1272 | if (err) | 1269 | if (err) |
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c index 3316caa4733b..b31f4791b8ff 100644 --- a/drivers/media/usb/tlg2300/pd-main.c +++ b/drivers/media/usb/tlg2300/pd-main.c | |||
| @@ -476,6 +476,8 @@ err_audio: | |||
| 476 | err_video: | 476 | err_video: |
| 477 | v4l2_device_unregister(&pd->v4l2_dev); | 477 | v4l2_device_unregister(&pd->v4l2_dev); |
| 478 | err_v4l2: | 478 | err_v4l2: |
| 479 | usb_put_intf(pd->interface); | ||
| 480 | usb_put_dev(pd->udev); | ||
| 479 | kfree(pd); | 481 | kfree(pd); |
| 480 | return ret; | 482 | return ret; |
| 481 | } | 483 | } |
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c index ea6070ba835e..b391194a840c 100644 --- a/drivers/media/usb/tlg2300/pd-radio.c +++ b/drivers/media/usb/tlg2300/pd-radio.c | |||
| @@ -327,7 +327,6 @@ int poseidon_fm_init(struct poseidon *p) | |||
| 327 | } | 327 | } |
| 328 | vfd->v4l2_dev = &p->v4l2_dev; | 328 | vfd->v4l2_dev = &p->v4l2_dev; |
| 329 | vfd->ctrl_handler = hdl; | 329 | vfd->ctrl_handler = hdl; |
| 330 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
| 331 | video_set_drvdata(vfd, p); | 330 | video_set_drvdata(vfd, p); |
| 332 | return video_register_device(vfd, VFL_TYPE_RADIO, -1); | 331 | return video_register_device(vfd, VFL_TYPE_RADIO, -1); |
| 333 | } | 332 | } |
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c index 8df668d06552..8cd7f02fcf9f 100644 --- a/drivers/media/usb/tlg2300/pd-video.c +++ b/drivers/media/usb/tlg2300/pd-video.c | |||
| @@ -1321,7 +1321,6 @@ static void init_video_context(struct running_context *context) | |||
| 1321 | .bytesperline = 720 * 2, | 1321 | .bytesperline = 720 * 2, |
| 1322 | .sizeimage = 720 * 576 * 2, | 1322 | .sizeimage = 720 * 576 * 2, |
| 1323 | .colorspace = V4L2_COLORSPACE_SMPTE170M, | 1323 | .colorspace = V4L2_COLORSPACE_SMPTE170M, |
| 1324 | .priv = 0 | ||
| 1325 | }; | 1324 | }; |
| 1326 | } | 1325 | } |
| 1327 | 1326 | ||
diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c index d1af5438c168..26b2ebb62547 100644 --- a/drivers/media/usb/tm6000/tm6000-input.c +++ b/drivers/media/usb/tm6000/tm6000-input.c | |||
| @@ -162,11 +162,42 @@ static int tm6000_ir_config(struct tm6000_IR *ir) | |||
| 162 | return 0; | 162 | return 0; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static void tm6000_ir_keydown(struct tm6000_IR *ir, | ||
| 166 | const char *buf, unsigned int len) | ||
| 167 | { | ||
| 168 | u8 device, command; | ||
| 169 | u32 scancode; | ||
| 170 | enum rc_type protocol; | ||
| 171 | |||
| 172 | if (len < 1) | ||
| 173 | return; | ||
| 174 | |||
| 175 | command = buf[0]; | ||
| 176 | device = (len > 1 ? buf[1] : 0x0); | ||
| 177 | switch (ir->rc_type) { | ||
| 178 | case RC_BIT_RC5: | ||
| 179 | protocol = RC_TYPE_RC5; | ||
| 180 | scancode = RC_SCANCODE_RC5(device, command); | ||
| 181 | break; | ||
| 182 | case RC_BIT_NEC: | ||
| 183 | protocol = RC_TYPE_NEC; | ||
| 184 | scancode = RC_SCANCODE_NEC(device, command); | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | protocol = RC_TYPE_OTHER; | ||
| 188 | scancode = RC_SCANCODE_OTHER(device << 8 | command); | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | |||
| 192 | dprintk(1, "%s, protocol: 0x%04x, scancode: 0x%08x\n", | ||
| 193 | __func__, protocol, scancode); | ||
| 194 | rc_keydown(ir->rc, protocol, scancode, 0); | ||
| 195 | } | ||
| 196 | |||
| 165 | static void tm6000_ir_urb_received(struct urb *urb) | 197 | static void tm6000_ir_urb_received(struct urb *urb) |
| 166 | { | 198 | { |
| 167 | struct tm6000_core *dev = urb->context; | 199 | struct tm6000_core *dev = urb->context; |
| 168 | struct tm6000_IR *ir = dev->ir; | 200 | struct tm6000_IR *ir = dev->ir; |
| 169 | struct tm6000_ir_poll_result poll_result; | ||
| 170 | char *buf; | 201 | char *buf; |
| 171 | 202 | ||
| 172 | dprintk(2, "%s\n",__func__); | 203 | dprintk(2, "%s\n",__func__); |
| @@ -184,12 +215,7 @@ static void tm6000_ir_urb_received(struct urb *urb) | |||
| 184 | DUMP_PREFIX_OFFSET,16, 1, | 215 | DUMP_PREFIX_OFFSET,16, 1, |
| 185 | buf, urb->actual_length, false); | 216 | buf, urb->actual_length, false); |
| 186 | 217 | ||
| 187 | poll_result.rc_data = buf[0]; | 218 | tm6000_ir_keydown(ir, urb->transfer_buffer, urb->actual_length); |
| 188 | if (urb->actual_length > 1) | ||
| 189 | poll_result.rc_data |= buf[1] << 8; | ||
| 190 | |||
| 191 | dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); | ||
| 192 | rc_keydown(ir->rc, poll_result.rc_data, 0); | ||
| 193 | 219 | ||
| 194 | usb_submit_urb(urb, GFP_ATOMIC); | 220 | usb_submit_urb(urb, GFP_ATOMIC); |
| 195 | /* | 221 | /* |
| @@ -204,7 +230,6 @@ static void tm6000_ir_handle_key(struct work_struct *work) | |||
| 204 | { | 230 | { |
| 205 | struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); | 231 | struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); |
| 206 | struct tm6000_core *dev = ir->dev; | 232 | struct tm6000_core *dev = ir->dev; |
| 207 | struct tm6000_ir_poll_result poll_result; | ||
| 208 | int rc; | 233 | int rc; |
| 209 | u8 buf[2]; | 234 | u8 buf[2]; |
| 210 | 235 | ||
| @@ -219,13 +244,8 @@ static void tm6000_ir_handle_key(struct work_struct *work) | |||
| 219 | if (rc < 0) | 244 | if (rc < 0) |
| 220 | return; | 245 | return; |
| 221 | 246 | ||
| 222 | if (rc > 1) | ||
| 223 | poll_result.rc_data = buf[0] | buf[1] << 8; | ||
| 224 | else | ||
| 225 | poll_result.rc_data = buf[0]; | ||
| 226 | |||
| 227 | /* Check if something was read */ | 247 | /* Check if something was read */ |
| 228 | if ((poll_result.rc_data & 0xff) == 0xff) { | 248 | if ((buf[0] & 0xff) == 0xff) { |
| 229 | if (!ir->pwled) { | 249 | if (!ir->pwled) { |
| 230 | tm6000_flash_led(dev, 1); | 250 | tm6000_flash_led(dev, 1); |
| 231 | ir->pwled = 1; | 251 | ir->pwled = 1; |
| @@ -233,8 +253,7 @@ static void tm6000_ir_handle_key(struct work_struct *work) | |||
| 233 | return; | 253 | return; |
| 234 | } | 254 | } |
| 235 | 255 | ||
| 236 | dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); | 256 | tm6000_ir_keydown(ir, buf, rc); |
| 237 | rc_keydown(ir->rc, poll_result.rc_data, 0); | ||
| 238 | tm6000_flash_led(dev, 0); | 257 | tm6000_flash_led(dev, 0); |
| 239 | ir->pwled = 0; | 258 | ir->pwled = 0; |
| 240 | 259 | ||
| @@ -422,9 +441,9 @@ int tm6000_ir_init(struct tm6000_core *dev) | |||
| 422 | ir->rc = rc; | 441 | ir->rc = rc; |
| 423 | 442 | ||
| 424 | /* input setup */ | 443 | /* input setup */ |
| 425 | rc_set_allowed_protocols(rc, RC_BIT_RC5 | RC_BIT_NEC); | 444 | rc->allowed_protocols = RC_BIT_RC5 | RC_BIT_NEC; |
| 426 | /* Neded, in order to support NEC remotes with 24 or 32 bits */ | 445 | /* Neded, in order to support NEC remotes with 24 or 32 bits */ |
| 427 | rc->scanmask = 0xffff; | 446 | rc->scancode_mask = 0xffff; |
| 428 | rc->priv = ir; | 447 | rc->priv = ir; |
| 429 | rc->change_protocol = tm6000_ir_change_protocol; | 448 | rc->change_protocol = tm6000_ir_change_protocol; |
| 430 | if (dev->int_in.endp) { | 449 | if (dev->int_in.endp) { |
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index e6b3d5d83d43..793577fc4633 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c | |||
| @@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
| 918 | (f->fmt.pix.width * fh->fmt->depth) >> 3; | 918 | (f->fmt.pix.width * fh->fmt->depth) >> 3; |
| 919 | f->fmt.pix.sizeimage = | 919 | f->fmt.pix.sizeimage = |
| 920 | f->fmt.pix.height * f->fmt.pix.bytesperline; | 920 | f->fmt.pix.height * f->fmt.pix.bytesperline; |
| 921 | f->fmt.pix.priv = 0; | ||
| 922 | 921 | ||
| 923 | return 0; | 922 | return 0; |
| 924 | } | 923 | } |
| @@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 959 | f->fmt.pix.width &= ~0x01; | 958 | f->fmt.pix.width &= ~0x01; |
| 960 | 959 | ||
| 961 | f->fmt.pix.field = field; | 960 | f->fmt.pix.field = field; |
| 962 | f->fmt.pix.priv = 0; | ||
| 963 | 961 | ||
| 964 | f->fmt.pix.bytesperline = | 962 | f->fmt.pix.bytesperline = |
| 965 | (f->fmt.pix.width * fmt->depth) >> 3; | 963 | (f->fmt.pix.width * fmt->depth) >> 3; |
| @@ -1626,7 +1624,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev, | |||
| 1626 | vfd->release = video_device_release; | 1624 | vfd->release = video_device_release; |
| 1627 | vfd->debug = tm6000_debug; | 1625 | vfd->debug = tm6000_debug; |
| 1628 | vfd->lock = &dev->lock; | 1626 | vfd->lock = &dev->lock; |
| 1629 | set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); | ||
| 1630 | 1627 | ||
| 1631 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); | 1628 | snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name); |
| 1632 | 1629 | ||
diff --git a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c index f8a60c197534..f166ffc9800a 100644 --- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c | |||
| @@ -791,8 +791,7 @@ static void ttusb_free_iso_urbs(struct ttusb *ttusb) | |||
| 791 | int i; | 791 | int i; |
| 792 | 792 | ||
| 793 | for (i = 0; i < ISO_BUF_COUNT; i++) | 793 | for (i = 0; i < ISO_BUF_COUNT; i++) |
| 794 | if (ttusb->iso_urb[i]) | 794 | usb_free_urb(ttusb->iso_urb[i]); |
| 795 | usb_free_urb(ttusb->iso_urb[i]); | ||
| 796 | 795 | ||
| 797 | pci_free_consistent(NULL, | 796 | pci_free_consistent(NULL, |
| 798 | ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * | 797 | ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * |
diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c index 2f87ddfa469f..473fab81b602 100644 --- a/drivers/media/usb/usbtv/usbtv-core.c +++ b/drivers/media/usb/usbtv/usbtv-core.c | |||
| @@ -91,6 +91,8 @@ static int usbtv_probe(struct usb_interface *intf, | |||
| 91 | return 0; | 91 | return 0; |
| 92 | 92 | ||
| 93 | usbtv_video_fail: | 93 | usbtv_video_fail: |
| 94 | usb_set_intfdata(intf, NULL); | ||
| 95 | usb_put_dev(usbtv->udev); | ||
| 94 | kfree(usbtv); | 96 | kfree(usbtv); |
| 95 | 97 | ||
| 96 | return ret; | 98 | return ret; |
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 2967e808408b..030c5854b4b3 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c | |||
| @@ -701,7 +701,6 @@ int usbtv_video_init(struct usbtv *usbtv) | |||
| 701 | usbtv->vdev.tvnorms = USBTV_TV_STD; | 701 | usbtv->vdev.tvnorms = USBTV_TV_STD; |
| 702 | usbtv->vdev.queue = &usbtv->vb2q; | 702 | usbtv->vdev.queue = &usbtv->vb2q; |
| 703 | usbtv->vdev.lock = &usbtv->v4l2_lock; | 703 | usbtv->vdev.lock = &usbtv->v4l2_lock; |
| 704 | set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags); | ||
| 705 | video_set_drvdata(&usbtv->vdev, usbtv); | 704 | video_set_drvdata(&usbtv->vdev, usbtv); |
| 706 | ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1); | 705 | ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1); |
| 707 | if (ret < 0) { | 706 | if (ret < 0) { |
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c index 816b1cffab7d..302aa07c458f 100644 --- a/drivers/media/usb/usbvision/usbvision-core.c +++ b/drivers/media/usb/usbvision/usbvision-core.c | |||
| @@ -1463,8 +1463,6 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address, | |||
| 1463 | 1463 | ||
| 1464 | static int usbvision_init_compression(struct usb_usbvision *usbvision) | 1464 | static int usbvision_init_compression(struct usb_usbvision *usbvision) |
| 1465 | { | 1465 | { |
| 1466 | int err_code = 0; | ||
| 1467 | |||
| 1468 | usbvision->last_isoc_frame_num = -1; | 1466 | usbvision->last_isoc_frame_num = -1; |
| 1469 | usbvision->isoc_data_count = 0; | 1467 | usbvision->isoc_data_count = 0; |
| 1470 | usbvision->isoc_packet_count = 0; | 1468 | usbvision->isoc_packet_count = 0; |
| @@ -1475,7 +1473,7 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision) | |||
| 1475 | usbvision->request_intra = 1; | 1473 | usbvision->request_intra = 1; |
| 1476 | usbvision->isoc_measure_bandwidth_count = 0; | 1474 | usbvision->isoc_measure_bandwidth_count = 0; |
| 1477 | 1475 | ||
| 1478 | return err_code; | 1476 | return 0; |
| 1479 | } | 1477 | } |
| 1480 | 1478 | ||
| 1481 | /* this function measures the used bandwidth since last call | 1479 | /* this function measures the used bandwidth since last call |
| @@ -1484,11 +1482,9 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision) | |||
| 1484 | */ | 1482 | */ |
| 1485 | static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision) | 1483 | static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision) |
| 1486 | { | 1484 | { |
| 1487 | int err_code = 0; | ||
| 1488 | |||
| 1489 | if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */ | 1485 | if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */ |
| 1490 | usbvision->isoc_measure_bandwidth_count++; | 1486 | usbvision->isoc_measure_bandwidth_count++; |
| 1491 | return err_code; | 1487 | return 0; |
| 1492 | } | 1488 | } |
| 1493 | if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) { | 1489 | if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) { |
| 1494 | usbvision->used_bandwidth = usbvision->isoc_data_count / | 1490 | usbvision->used_bandwidth = usbvision->isoc_data_count / |
| @@ -1499,7 +1495,7 @@ static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision) | |||
| 1499 | usbvision->isoc_data_count = 0; | 1495 | usbvision->isoc_data_count = 0; |
| 1500 | usbvision->isoc_packet_count = 0; | 1496 | usbvision->isoc_packet_count = 0; |
| 1501 | usbvision->isoc_skip_count = 0; | 1497 | usbvision->isoc_skip_count = 0; |
| 1502 | return err_code; | 1498 | return 0; |
| 1503 | } | 1499 | } |
| 1504 | 1500 | ||
| 1505 | static int usbvision_adjust_compression(struct usb_usbvision *usbvision) | 1501 | static int usbvision_adjust_compression(struct usb_usbvision *usbvision) |
| @@ -1546,26 +1542,24 @@ static int usbvision_adjust_compression(struct usb_usbvision *usbvision) | |||
| 1546 | 1542 | ||
| 1547 | static int usbvision_request_intra(struct usb_usbvision *usbvision) | 1543 | static int usbvision_request_intra(struct usb_usbvision *usbvision) |
| 1548 | { | 1544 | { |
| 1549 | int err_code = 0; | ||
| 1550 | unsigned char buffer[1]; | 1545 | unsigned char buffer[1]; |
| 1551 | 1546 | ||
| 1552 | PDEBUG(DBG_IRQ, ""); | 1547 | PDEBUG(DBG_IRQ, ""); |
| 1553 | usbvision->request_intra = 1; | 1548 | usbvision->request_intra = 1; |
| 1554 | buffer[0] = 1; | 1549 | buffer[0] = 1; |
| 1555 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | 1550 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); |
| 1556 | return err_code; | 1551 | return 0; |
| 1557 | } | 1552 | } |
| 1558 | 1553 | ||
| 1559 | static int usbvision_unrequest_intra(struct usb_usbvision *usbvision) | 1554 | static int usbvision_unrequest_intra(struct usb_usbvision *usbvision) |
| 1560 | { | 1555 | { |
| 1561 | int err_code = 0; | ||
| 1562 | unsigned char buffer[1]; | 1556 | unsigned char buffer[1]; |
| 1563 | 1557 | ||
| 1564 | PDEBUG(DBG_IRQ, ""); | 1558 | PDEBUG(DBG_IRQ, ""); |
| 1565 | usbvision->request_intra = 0; | 1559 | usbvision->request_intra = 0; |
| 1566 | buffer[0] = 0; | 1560 | buffer[0] = 0; |
| 1567 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); | 1561 | usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); |
| 1568 | return err_code; | 1562 | return 0; |
| 1569 | } | 1563 | } |
| 1570 | 1564 | ||
| 1571 | /******************************* | 1565 | /******************************* |
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index ad47c5cb539a..f8135f4e3b52 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c | |||
| @@ -1746,7 +1746,6 @@ static int uvc_register_video(struct uvc_device *dev, | |||
| 1746 | vdev->fops = &uvc_fops; | 1746 | vdev->fops = &uvc_fops; |
| 1747 | vdev->release = uvc_release; | 1747 | vdev->release = uvc_release; |
| 1748 | vdev->prio = &stream->chain->prio; | 1748 | vdev->prio = &stream->chain->prio; |
| 1749 | set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); | ||
| 1750 | if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | 1749 | if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) |
| 1751 | vdev->vfl_dir = VFL_DIR_TX; | 1750 | vdev->vfl_dir = VFL_DIR_TX; |
| 1752 | strlcpy(vdev->name, dev->name, sizeof vdev->name); | 1751 | strlcpy(vdev->name, dev->name, sizeof vdev->name); |
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 74d56df3347f..5c006277b8b1 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c | |||
| @@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
| 806 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 806 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
| 807 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 807 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
| 808 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; | 808 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; |
| 809 | f->fmt.pix.priv = 0; | ||
| 810 | DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, | 809 | DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__, |
| 811 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), | 810 | decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name), |
| 812 | f->fmt.pix.field); | 811 | f->fmt.pix.field); |
| @@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
| 829 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 828 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
| 830 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 829 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
| 831 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; | 830 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; |
| 832 | f->fmt.pix.priv = 0; | ||
| 833 | return 0; | 831 | return 0; |
| 834 | } | 832 | } |
| 835 | 833 | ||
| @@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
| 866 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; | 864 | f->fmt.pix.bytesperline = f->fmt.pix.width * 2; |
| 867 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 865 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
| 868 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; | 866 | f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; |
| 869 | f->fmt.pix.priv = 0; | ||
| 870 | cam->vb_vidq.field = f->fmt.pix.field; | 867 | cam->vb_vidq.field = f->fmt.pix.field; |
| 871 | 868 | ||
| 872 | if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) | 869 | if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120) |
| @@ -1456,7 +1453,6 @@ static int zr364xx_probe(struct usb_interface *intf, | |||
| 1456 | cam->vdev.lock = &cam->lock; | 1453 | cam->vdev.lock = &cam->lock; |
| 1457 | cam->vdev.v4l2_dev = &cam->v4l2_dev; | 1454 | cam->vdev.v4l2_dev = &cam->v4l2_dev; |
| 1458 | cam->vdev.ctrl_handler = &cam->ctrl_handler; | 1455 | cam->vdev.ctrl_handler = &cam->ctrl_handler; |
| 1459 | set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags); | ||
| 1460 | video_set_drvdata(&cam->vdev, cam); | 1456 | video_set_drvdata(&cam->vdev, cam); |
| 1461 | if (debug) | 1457 | if (debug) |
| 1462 | cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; | 1458 | cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; |
