aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx/em28xx-video.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2013-12-22 13:28:26 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-01-05 05:58:16 -0500
commit0560f337f3282dc6bf77b13ac344ffe30d9ccce5 (patch)
tree63f0105442382f0b3fc9d1c985432ee1960c74a0 /drivers/media/usb/em28xx/em28xx-video.c
parent547bf2508146f0274e4b72793c5017ca276282b6 (diff)
[media] em28xx: move some video-specific functions to em28xx-video
Now that we want to split the video handling to a separate module, move all video-specific functions to em28xx-video. No functional changes. Reviewed-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c374
1 files changed, 370 insertions, 4 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index dd19c9ff76e0..51d440588ed5 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -53,15 +53,23 @@
53 53
54#define EM28XX_VERSION "0.2.0" 54#define EM28XX_VERSION "0.2.0"
55 55
56static unsigned int isoc_debug;
57module_param(isoc_debug, int, 0644);
58MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
59
60static unsigned int disable_vbi;
61module_param(disable_vbi, int, 0644);
62MODULE_PARM_DESC(disable_vbi, "disable vbi support");
63
64static int alt;
65module_param(alt, int, 0644);
66MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
67
56#define em28xx_videodbg(fmt, arg...) do {\ 68#define em28xx_videodbg(fmt, arg...) do {\
57 if (video_debug) \ 69 if (video_debug) \
58 printk(KERN_INFO "%s %s :"fmt, \ 70 printk(KERN_INFO "%s %s :"fmt, \
59 dev->name, __func__ , ##arg); } while (0) 71 dev->name, __func__ , ##arg); } while (0)
60 72
61static unsigned int isoc_debug;
62module_param(isoc_debug, int, 0644);
63MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
64
65#define em28xx_isocdbg(fmt, arg...) \ 73#define em28xx_isocdbg(fmt, arg...) \
66do {\ 74do {\
67 if (isoc_debug) { \ 75 if (isoc_debug) { \
@@ -135,6 +143,257 @@ static struct em28xx_fmt format[] = {
135 }, 143 },
136}; 144};
137 145
146int em28xx_vbi_supported(struct em28xx *dev)
147{
148 /* Modprobe option to manually disable */
149 if (disable_vbi == 1)
150 return 0;
151
152 if (dev->board.is_webcam)
153 return 0;
154
155 /* FIXME: check subdevices for VBI support */
156
157 if (dev->chip_id == CHIP_ID_EM2860 ||
158 dev->chip_id == CHIP_ID_EM2883)
159 return 1;
160
161 /* Version of em28xx that does not support VBI */
162 return 0;
163}
164
165/*
166 * em28xx_wake_i2c()
167 * configure i2c attached devices
168 */
169void em28xx_wake_i2c(struct em28xx *dev)
170{
171 v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
172 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
173 INPUT(dev->ctl_input)->vmux, 0, 0);
174 v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
175}
176
177int em28xx_colorlevels_set_default(struct em28xx *dev)
178{
179 em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
180 em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
181 em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
182 em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
183 em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
184 em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
185
186 em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
187 em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
188 em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
189 em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
190 em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
191 em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
192 return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
193}
194
195int em28xx_set_outfmt(struct em28xx *dev)
196{
197 int ret;
198 u8 fmt, vinctrl;
199
200 fmt = dev->format->reg;
201 if (!dev->is_em25xx)
202 fmt |= 0x20;
203 /*
204 * NOTE: it's not clear if this is really needed !
205 * The datasheets say bit 5 is a reserved bit and devices seem to work
206 * fine without it. But the Windows driver sets it for em2710/50+em28xx
207 * devices and we've always been setting it, too.
208 *
209 * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
210 * it's likely used for an additional (compressed ?) format there.
211 */
212 ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
213 if (ret < 0)
214 return ret;
215
216 ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
217 if (ret < 0)
218 return ret;
219
220 vinctrl = dev->vinctl;
221 if (em28xx_vbi_supported(dev) == 1) {
222 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
223 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
224 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
225 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
226 if (dev->norm & V4L2_STD_525_60) {
227 /* NTSC */
228 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
229 } else if (dev->norm & V4L2_STD_625_50) {
230 /* PAL */
231 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
232 }
233 }
234
235 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
236}
237
238static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
239 u8 ymin, u8 ymax)
240{
241 em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
242 xmin, ymin, xmax, ymax);
243
244 em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
245 em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
246 em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
247 return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
248}
249
250static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
251 u16 width, u16 height)
252{
253 u8 cwidth = width >> 2;
254 u8 cheight = height >> 2;
255 u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
256 /* NOTE: size limit: 2047x1023 = 2MPix */
257
258 em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
259 hstart, vstart,
260 ((overflow & 2) << 9 | cwidth << 2),
261 ((overflow & 1) << 10 | cheight << 2));
262
263 em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
264 em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
265 em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
266 em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
267 em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
268
269 /* FIXME: function/meaning of these registers ? */
270 /* FIXME: align width+height to multiples of 4 ?! */
271 if (dev->is_em25xx) {
272 em28xx_write_reg(dev, 0x34, width >> 4);
273 em28xx_write_reg(dev, 0x35, height >> 4);
274 }
275}
276
277static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
278{
279 u8 mode;
280 /* the em2800 scaler only supports scaling down to 50% */
281
282 if (dev->board.is_em2800) {
283 mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
284 } else {
285 u8 buf[2];
286
287 buf[0] = h;
288 buf[1] = h >> 8;
289 em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
290
291 buf[0] = v;
292 buf[1] = v >> 8;
293 em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
294 /* it seems that both H and V scalers must be active
295 to work correctly */
296 mode = (h || v) ? 0x30 : 0x00;
297 }
298 return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
299}
300
301/* FIXME: this only function read values from dev */
302int em28xx_resolution_set(struct em28xx *dev)
303{
304 int width, height;
305 width = norm_maxw(dev);
306 height = norm_maxh(dev);
307
308 /* Properly setup VBI */
309 dev->vbi_width = 720;
310 if (dev->norm & V4L2_STD_525_60)
311 dev->vbi_height = 12;
312 else
313 dev->vbi_height = 18;
314
315 em28xx_set_outfmt(dev);
316
317 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
318
319 /* If we don't set the start position to 2 in VBI mode, we end up
320 with line 20/21 being YUYV encoded instead of being in 8-bit
321 greyscale. The core of the issue is that line 21 (and line 23 for
322 PAL WSS) are inside of active video region, and as a result they
323 get the pixelformatting associated with that area. So by cropping
324 it out, we end up with the same format as the rest of the VBI
325 region */
326 if (em28xx_vbi_supported(dev) == 1)
327 em28xx_capture_area_set(dev, 0, 2, width, height);
328 else
329 em28xx_capture_area_set(dev, 0, 0, width, height);
330
331 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
332}
333
334/* Set USB alternate setting for analog video */
335int em28xx_set_alternate(struct em28xx *dev)
336{
337 int errCode;
338 int i;
339 unsigned int min_pkt_size = dev->width * 2 + 4;
340
341 /* NOTE: for isoc transfers, only alt settings > 0 are allowed
342 bulk transfers seem to work only with alt=0 ! */
343 dev->alt = 0;
344 if ((alt > 0) && (alt < dev->num_alt)) {
345 em28xx_videodbg("alternate forced to %d\n", dev->alt);
346 dev->alt = alt;
347 goto set_alt;
348 }
349 if (dev->analog_xfer_bulk)
350 goto set_alt;
351
352 /* When image size is bigger than a certain value,
353 the frame size should be increased, otherwise, only
354 green screen will be received.
355 */
356 if (dev->width * 2 * dev->height > 720 * 240 * 2)
357 min_pkt_size *= 2;
358
359 for (i = 0; i < dev->num_alt; i++) {
360 /* stop when the selected alt setting offers enough bandwidth */
361 if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
362 dev->alt = i;
363 break;
364 /* otherwise make sure that we end up with the maximum bandwidth
365 because the min_pkt_size equation might be wrong...
366 */
367 } else if (dev->alt_max_pkt_size_isoc[i] >
368 dev->alt_max_pkt_size_isoc[dev->alt])
369 dev->alt = i;
370 }
371
372set_alt:
373 /* NOTE: for bulk transfers, we need to call usb_set_interface()
374 * even if the previous settings were the same. Otherwise streaming
375 * fails with all urbs having status = -EOVERFLOW ! */
376 if (dev->analog_xfer_bulk) {
377 dev->max_pkt_size = 512; /* USB 2.0 spec */
378 dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
379 } else { /* isoc */
380 em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
381 min_pkt_size, dev->alt);
382 dev->max_pkt_size =
383 dev->alt_max_pkt_size_isoc[dev->alt];
384 dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
385 }
386 em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
387 dev->alt, dev->max_pkt_size);
388 errCode = usb_set_interface(dev->udev, 0, dev->alt);
389 if (errCode < 0) {
390 em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
391 dev->alt, errCode);
392 return errCode;
393 }
394 return 0;
395}
396
138/* ------------------------------------------------------------------ 397/* ------------------------------------------------------------------
139 DMA and thread functions 398 DMA and thread functions
140 ------------------------------------------------------------------*/ 399 ------------------------------------------------------------------*/
@@ -1817,6 +2076,113 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
1817 return vfd; 2076 return vfd;
1818} 2077}
1819 2078
2079static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
2080{
2081 memset(ctl, 0, sizeof(*ctl));
2082
2083 ctl->fname = XC2028_DEFAULT_FIRMWARE;
2084 ctl->max_len = 64;
2085 ctl->mts = em28xx_boards[dev->model].mts_firmware;
2086
2087 switch (dev->model) {
2088 case EM2880_BOARD_EMPIRE_DUAL_TV:
2089 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
2090 case EM2882_BOARD_TERRATEC_HYBRID_XS:
2091 ctl->demod = XC3028_FE_ZARLINK456;
2092 break;
2093 case EM2880_BOARD_TERRATEC_HYBRID_XS:
2094 case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
2095 case EM2881_BOARD_PINNACLE_HYBRID_PRO:
2096 ctl->demod = XC3028_FE_ZARLINK456;
2097 break;
2098 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
2099 case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
2100 ctl->demod = XC3028_FE_DEFAULT;
2101 break;
2102 case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
2103 ctl->demod = XC3028_FE_DEFAULT;
2104 ctl->fname = XC3028L_DEFAULT_FIRMWARE;
2105 break;
2106 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
2107 case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
2108 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
2109 /* FIXME: Better to specify the needed IF */
2110 ctl->demod = XC3028_FE_DEFAULT;
2111 break;
2112 case EM2883_BOARD_KWORLD_HYBRID_330U:
2113 case EM2882_BOARD_DIKOM_DK300:
2114 case EM2882_BOARD_KWORLD_VS_DVBT:
2115 ctl->demod = XC3028_FE_CHINA;
2116 ctl->fname = XC2028_DEFAULT_FIRMWARE;
2117 break;
2118 case EM2882_BOARD_EVGA_INDTUBE:
2119 ctl->demod = XC3028_FE_CHINA;
2120 ctl->fname = XC3028L_DEFAULT_FIRMWARE;
2121 break;
2122 default:
2123 ctl->demod = XC3028_FE_OREN538;
2124 }
2125}
2126
2127void em28xx_tuner_setup(struct em28xx *dev)
2128{
2129 struct tuner_setup tun_setup;
2130 struct v4l2_frequency f;
2131
2132 if (dev->tuner_type == TUNER_ABSENT)
2133 return;
2134
2135 memset(&tun_setup, 0, sizeof(tun_setup));
2136
2137 tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
2138 tun_setup.tuner_callback = em28xx_tuner_callback;
2139
2140 if (dev->board.radio.type) {
2141 tun_setup.type = dev->board.radio.type;
2142 tun_setup.addr = dev->board.radio_addr;
2143
2144 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2145 }
2146
2147 if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
2148 tun_setup.type = dev->tuner_type;
2149 tun_setup.addr = dev->tuner_addr;
2150
2151 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
2152 }
2153
2154 if (dev->tda9887_conf) {
2155 struct v4l2_priv_tun_config tda9887_cfg;
2156
2157 tda9887_cfg.tuner = TUNER_TDA9887;
2158 tda9887_cfg.priv = &dev->tda9887_conf;
2159
2160 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
2161 }
2162
2163 if (dev->tuner_type == TUNER_XC2028) {
2164 struct v4l2_priv_tun_config xc2028_cfg;
2165 struct xc2028_ctrl ctl;
2166
2167 memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
2168 memset(&ctl, 0, sizeof(ctl));
2169
2170 em28xx_setup_xc3028(dev, &ctl);
2171
2172 xc2028_cfg.tuner = TUNER_XC2028;
2173 xc2028_cfg.priv = &ctl;
2174
2175 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
2176 }
2177
2178 /* configure tuner */
2179 f.tuner = 0;
2180 f.type = V4L2_TUNER_ANALOG_TV;
2181 f.frequency = 9076; /* just a magic number */
2182 dev->ctl_freq = f.frequency;
2183 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
2184}
2185
1820int em28xx_register_analog_devices(struct em28xx *dev) 2186int em28xx_register_analog_devices(struct em28xx *dev)
1821{ 2187{
1822 u8 val; 2188 u8 val;