From: Mauro Carvalho Chehab <m.chehab@samsung.com>
To: "Frank Schäfer" <fschaefer.oss@googlemail.com>
Cc: Linux Media Mailing List <linux-media@vger.kernel.org>,
Mauro Carvalho Chehab <mchehab@infradead.org>
Subject: Re: [PATCH v4 01/22] [media] em28xx: move some video-specific functions to em28xx-video
Date: Sun, 05 Jan 2014 11:28:45 -0200 [thread overview]
Message-ID: <20140105112845.71a44854@samsung.com> (raw)
In-Reply-To: <52C92FC8.1060801@googlemail.com>
Em Sun, 05 Jan 2014 11:11:20 +0100
Frank Schäfer <fschaefer.oss@googlemail.com> escreveu:
> Am 04.01.2014 11:55, schrieb Mauro Carvalho Chehab:
> > Now that we want to split the video handling to a separate
> > module, move all video-specific functions to em28xx-video.
> >
> > No functional changes.
> >
> > Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
> > ---
> > drivers/media/usb/em28xx/em28xx-cards.c | 107 ---------
> > drivers/media/usb/em28xx/em28xx-core.c | 259 ----------------------
> > drivers/media/usb/em28xx/em28xx-video.c | 374 +++++++++++++++++++++++++++++++-
> > drivers/media/usb/em28xx/em28xx.h | 1 +
> > 4 files changed, 371 insertions(+), 370 deletions(-)
> >
> > diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
> > index 36853f16bf97..19827e79cf53 100644
> > --- a/drivers/media/usb/em28xx/em28xx-cards.c
> > +++ b/drivers/media/usb/em28xx/em28xx-cards.c
> > @@ -2529,113 +2529,6 @@ static void em28xx_pre_card_setup(struct em28xx *dev)
> > em28xx_set_mode(dev, EM28XX_SUSPEND);
> > }
> >
> > -static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
> > -{
> > - memset(ctl, 0, sizeof(*ctl));
> > -
> > - ctl->fname = XC2028_DEFAULT_FIRMWARE;
> > - ctl->max_len = 64;
> > - ctl->mts = em28xx_boards[dev->model].mts_firmware;
> > -
> > - switch (dev->model) {
> > - case EM2880_BOARD_EMPIRE_DUAL_TV:
> > - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
> > - case EM2882_BOARD_TERRATEC_HYBRID_XS:
> > - ctl->demod = XC3028_FE_ZARLINK456;
> > - break;
> > - case EM2880_BOARD_TERRATEC_HYBRID_XS:
> > - case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
> > - case EM2881_BOARD_PINNACLE_HYBRID_PRO:
> > - ctl->demod = XC3028_FE_ZARLINK456;
> > - break;
> > - case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
> > - case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
> > - ctl->demod = XC3028_FE_DEFAULT;
> > - break;
> > - case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
> > - ctl->demod = XC3028_FE_DEFAULT;
> > - ctl->fname = XC3028L_DEFAULT_FIRMWARE;
> > - break;
> > - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
> > - case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
> > - case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
> > - /* FIXME: Better to specify the needed IF */
> > - ctl->demod = XC3028_FE_DEFAULT;
> > - break;
> > - case EM2883_BOARD_KWORLD_HYBRID_330U:
> > - case EM2882_BOARD_DIKOM_DK300:
> > - case EM2882_BOARD_KWORLD_VS_DVBT:
> > - ctl->demod = XC3028_FE_CHINA;
> > - ctl->fname = XC2028_DEFAULT_FIRMWARE;
> > - break;
> > - case EM2882_BOARD_EVGA_INDTUBE:
> > - ctl->demod = XC3028_FE_CHINA;
> > - ctl->fname = XC3028L_DEFAULT_FIRMWARE;
> > - break;
> > - default:
> > - ctl->demod = XC3028_FE_OREN538;
> > - }
> > -}
> > -
> > -static void em28xx_tuner_setup(struct em28xx *dev)
> > -{
> > - struct tuner_setup tun_setup;
> > - struct v4l2_frequency f;
> > -
> > - if (dev->tuner_type == TUNER_ABSENT)
> > - return;
> > -
> > - memset(&tun_setup, 0, sizeof(tun_setup));
> > -
> > - tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
> > - tun_setup.tuner_callback = em28xx_tuner_callback;
> > -
> > - if (dev->board.radio.type) {
> > - tun_setup.type = dev->board.radio.type;
> > - tun_setup.addr = dev->board.radio_addr;
> > -
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
> > - }
> > -
> > - if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
> > - tun_setup.type = dev->tuner_type;
> > - tun_setup.addr = dev->tuner_addr;
> > -
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
> > - }
> > -
> > - if (dev->tda9887_conf) {
> > - struct v4l2_priv_tun_config tda9887_cfg;
> > -
> > - tda9887_cfg.tuner = TUNER_TDA9887;
> > - tda9887_cfg.priv = &dev->tda9887_conf;
> > -
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
> > - }
> > -
> > - if (dev->tuner_type == TUNER_XC2028) {
> > - struct v4l2_priv_tun_config xc2028_cfg;
> > - struct xc2028_ctrl ctl;
> > -
> > - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
> > - memset(&ctl, 0, sizeof(ctl));
> > -
> > - em28xx_setup_xc3028(dev, &ctl);
> > -
> > - xc2028_cfg.tuner = TUNER_XC2028;
> > - xc2028_cfg.priv = &ctl;
> > -
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
> > - }
> > -
> > - /* configure tuner */
> > - f.tuner = 0;
> > - f.type = V4L2_TUNER_ANALOG_TV;
> > - f.frequency = 9076; /* just a magic number */
> > - dev->ctl_freq = f.frequency;
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
> > -}
> > -
> > static int em28xx_hint_board(struct em28xx *dev)
> > {
> > int i;
> > diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
> > index f6076a512e8f..3012912d2997 100644
> > --- a/drivers/media/usb/em28xx/em28xx-core.c
> > +++ b/drivers/media/usb/em28xx/em28xx-core.c
> > @@ -53,14 +53,6 @@ MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
> > printk(KERN_INFO "%s %s :"fmt, \
> > dev->name, __func__ , ##arg); } while (0)
> >
> > -static int alt;
> > -module_param(alt, int, 0644);
> > -MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
> > -
> > -static unsigned int disable_vbi;
> > -module_param(disable_vbi, int, 0644);
> > -MODULE_PARM_DESC(disable_vbi, "disable vbi support");
> > -
> > /* FIXME */
> > #define em28xx_isocdbg(fmt, arg...) do {\
> > if (core_debug) \
> > @@ -603,24 +595,6 @@ init_audio:
> > }
> > EXPORT_SYMBOL_GPL(em28xx_audio_setup);
> >
> > -int em28xx_colorlevels_set_default(struct em28xx *dev)
> > -{
> > - em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
> > - em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
> > - em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
> > - em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
> > - em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
> > - em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
> > -
> > - em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
> > - em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
> > - em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
> > - em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
> > - em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
> > - em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
> > - return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
> > -}
> > -
> > const struct em28xx_led *em28xx_find_led(struct em28xx *dev,
> > enum em28xx_led_role role)
> > {
> > @@ -696,227 +670,6 @@ int em28xx_capture_start(struct em28xx *dev, int start)
> > return rc;
> > }
> >
> > -int em28xx_vbi_supported(struct em28xx *dev)
> > -{
> > - /* Modprobe option to manually disable */
> > - if (disable_vbi == 1)
> > - return 0;
> > -
> > - if (dev->board.is_webcam)
> > - return 0;
> > -
> > - /* FIXME: check subdevices for VBI support */
> > -
> > - if (dev->chip_id == CHIP_ID_EM2860 ||
> > - dev->chip_id == CHIP_ID_EM2883)
> > - return 1;
> > -
> > - /* Version of em28xx that does not support VBI */
> > - return 0;
> > -}
> > -
> > -int em28xx_set_outfmt(struct em28xx *dev)
> > -{
> > - int ret;
> > - u8 fmt, vinctrl;
> > -
> > - fmt = dev->format->reg;
> > - if (!dev->is_em25xx)
> > - fmt |= 0x20;
> > - /*
> > - * NOTE: it's not clear if this is really needed !
> > - * The datasheets say bit 5 is a reserved bit and devices seem to work
> > - * fine without it. But the Windows driver sets it for em2710/50+em28xx
> > - * devices and we've always been setting it, too.
> > - *
> > - * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
> > - * it's likely used for an additional (compressed ?) format there.
> > - */
> > - ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
> > - if (ret < 0)
> > - return ret;
> > -
> > - ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
> > - if (ret < 0)
> > - return ret;
> > -
> > - vinctrl = dev->vinctl;
> > - if (em28xx_vbi_supported(dev) == 1) {
> > - vinctrl |= EM28XX_VINCTRL_VBI_RAW;
> > - em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
> > - em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
> > - em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
> > - if (dev->norm & V4L2_STD_525_60) {
> > - /* NTSC */
> > - em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
> > - } else if (dev->norm & V4L2_STD_625_50) {
> > - /* PAL */
> > - em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
> > - }
> > - }
> > -
> > - return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
> > -}
> > -
> > -static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
> > - u8 ymin, u8 ymax)
> > -{
> > - em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
> > - xmin, ymin, xmax, ymax);
> > -
> > - em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
> > - em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
> > - em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
> > - return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
> > -}
> > -
> > -static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
> > - u16 width, u16 height)
> > -{
> > - u8 cwidth = width >> 2;
> > - u8 cheight = height >> 2;
> > - u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
> > - /* NOTE: size limit: 2047x1023 = 2MPix */
> > -
> > - em28xx_coredbg("capture area set to (%d,%d): %dx%d\n",
> > - hstart, vstart,
> > - ((overflow & 2) << 9 | cwidth << 2),
> > - ((overflow & 1) << 10 | cheight << 2));
> > -
> > - em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
> > - em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
> > - em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
> > - em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
> > - em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
> > -
> > - /* FIXME: function/meaning of these registers ? */
> > - /* FIXME: align width+height to multiples of 4 ?! */
> > - if (dev->is_em25xx) {
> > - em28xx_write_reg(dev, 0x34, width >> 4);
> > - em28xx_write_reg(dev, 0x35, height >> 4);
> > - }
> > -}
> > -
> > -static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
> > -{
> > - u8 mode;
> > - /* the em2800 scaler only supports scaling down to 50% */
> > -
> > - if (dev->board.is_em2800) {
> > - mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
> > - } else {
> > - u8 buf[2];
> > -
> > - buf[0] = h;
> > - buf[1] = h >> 8;
> > - em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
> > -
> > - buf[0] = v;
> > - buf[1] = v >> 8;
> > - em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
> > - /* it seems that both H and V scalers must be active
> > - to work correctly */
> > - mode = (h || v) ? 0x30 : 0x00;
> > - }
> > - return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
> > -}
> > -
> > -/* FIXME: this only function read values from dev */
> > -int em28xx_resolution_set(struct em28xx *dev)
> > -{
> > - int width, height;
> > - width = norm_maxw(dev);
> > - height = norm_maxh(dev);
> > -
> > - /* Properly setup VBI */
> > - dev->vbi_width = 720;
> > - if (dev->norm & V4L2_STD_525_60)
> > - dev->vbi_height = 12;
> > - else
> > - dev->vbi_height = 18;
> > -
> > - em28xx_set_outfmt(dev);
> > -
> > - em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
> > -
> > - /* If we don't set the start position to 2 in VBI mode, we end up
> > - with line 20/21 being YUYV encoded instead of being in 8-bit
> > - greyscale. The core of the issue is that line 21 (and line 23 for
> > - PAL WSS) are inside of active video region, and as a result they
> > - get the pixelformatting associated with that area. So by cropping
> > - it out, we end up with the same format as the rest of the VBI
> > - region */
> > - if (em28xx_vbi_supported(dev) == 1)
> > - em28xx_capture_area_set(dev, 0, 2, width, height);
> > - else
> > - em28xx_capture_area_set(dev, 0, 0, width, height);
> > -
> > - return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
> > -}
> > -
> > -/* Set USB alternate setting for analog video */
> > -int em28xx_set_alternate(struct em28xx *dev)
> > -{
> > - int errCode;
> > - int i;
> > - unsigned int min_pkt_size = dev->width * 2 + 4;
> > -
> > - /* NOTE: for isoc transfers, only alt settings > 0 are allowed
> > - bulk transfers seem to work only with alt=0 ! */
> > - dev->alt = 0;
> > - if ((alt > 0) && (alt < dev->num_alt)) {
> > - em28xx_coredbg("alternate forced to %d\n", dev->alt);
> > - dev->alt = alt;
> > - goto set_alt;
> > - }
> > - if (dev->analog_xfer_bulk)
> > - goto set_alt;
> > -
> > - /* When image size is bigger than a certain value,
> > - the frame size should be increased, otherwise, only
> > - green screen will be received.
> > - */
> > - if (dev->width * 2 * dev->height > 720 * 240 * 2)
> > - min_pkt_size *= 2;
> > -
> > - for (i = 0; i < dev->num_alt; i++) {
> > - /* stop when the selected alt setting offers enough bandwidth */
> > - if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
> > - dev->alt = i;
> > - break;
> > - /* otherwise make sure that we end up with the maximum bandwidth
> > - because the min_pkt_size equation might be wrong...
> > - */
> > - } else if (dev->alt_max_pkt_size_isoc[i] >
> > - dev->alt_max_pkt_size_isoc[dev->alt])
> > - dev->alt = i;
> > - }
> > -
> > -set_alt:
> > - /* NOTE: for bulk transfers, we need to call usb_set_interface()
> > - * even if the previous settings were the same. Otherwise streaming
> > - * fails with all urbs having status = -EOVERFLOW ! */
> > - if (dev->analog_xfer_bulk) {
> > - dev->max_pkt_size = 512; /* USB 2.0 spec */
> > - dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
> > - } else { /* isoc */
> > - em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
> > - min_pkt_size, dev->alt);
> > - dev->max_pkt_size =
> > - dev->alt_max_pkt_size_isoc[dev->alt];
> > - dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
> > - }
> > - em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
> > - dev->alt, dev->max_pkt_size);
> > - errCode = usb_set_interface(dev->udev, 0, dev->alt);
> > - if (errCode < 0) {
> > - em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
> > - dev->alt, errCode);
> > - return errCode;
> > - }
> > - return 0;
> > -}
> > -
> > int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
> > {
> > int rc = 0;
> > @@ -1282,18 +1035,6 @@ int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
> > EXPORT_SYMBOL_GPL(em28xx_init_usb_xfer);
> >
> > /*
> > - * em28xx_wake_i2c()
> > - * configure i2c attached devices
> > - */
> > -void em28xx_wake_i2c(struct em28xx *dev)
> > -{
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
> > - INPUT(dev->ctl_input)->vmux, 0, 0);
> > - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
> > -}
> > -
> > -/*
> > * Device control list
> > */
> >
> > diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
> > index dd19c9ff76e0..70ffe259df5b 100644
> > --- a/drivers/media/usb/em28xx/em28xx-video.c
> > +++ b/drivers/media/usb/em28xx/em28xx-video.c
> > @@ -53,15 +53,23 @@
> >
> > #define EM28XX_VERSION "0.2.0"
> >
> > +static unsigned int isoc_debug;
> > +module_param(isoc_debug, int, 0644);
> > +MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
> > +
> > +static unsigned int disable_vbi;
> > +module_param(disable_vbi, int, 0644);
> > +MODULE_PARM_DESC(disable_vbi, "disable vbi support");
> > +
> > +static int alt;
> > +module_param(alt, int, 0644);
> > +MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
> > +
> > #define em28xx_videodbg(fmt, arg...) do {\
> > if (video_debug) \
> > printk(KERN_INFO "%s %s :"fmt, \
> > dev->name, __func__ , ##arg); } while (0)
> >
> > -static unsigned int isoc_debug;
> > -module_param(isoc_debug, int, 0644);
> > -MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
> > -
> > #define em28xx_isocdbg(fmt, arg...) \
> > do {\
> > if (isoc_debug) { \
> > @@ -135,6 +143,257 @@ static struct em28xx_fmt format[] = {
> > },
> > };
> >
> > +/*
> > + * em28xx_wake_i2c()
> > + * configure i2c attached devices
> > + */
> > +void em28xx_wake_i2c(struct em28xx *dev)
> > +{
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
> > + INPUT(dev->ctl_input)->vmux, 0, 0);
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
> > +}
> > +
> > +int em28xx_colorlevels_set_default(struct em28xx *dev)
> > +{
> > + em28xx_write_reg(dev, EM28XX_R20_YGAIN, CONTRAST_DEFAULT);
> > + em28xx_write_reg(dev, EM28XX_R21_YOFFSET, BRIGHTNESS_DEFAULT);
> > + em28xx_write_reg(dev, EM28XX_R22_UVGAIN, SATURATION_DEFAULT);
> > + em28xx_write_reg(dev, EM28XX_R23_UOFFSET, BLUE_BALANCE_DEFAULT);
> > + em28xx_write_reg(dev, EM28XX_R24_VOFFSET, RED_BALANCE_DEFAULT);
> > + em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, SHARPNESS_DEFAULT);
> > +
> > + em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
> > + em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
> > + em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
> > + em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
> > + em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
> > + em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
> > + return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
> > +}
> > +
> > +int em28xx_set_outfmt(struct em28xx *dev)
> > +{
> > + int ret;
> > + u8 fmt, vinctrl;
> > +
> > + fmt = dev->format->reg;
> > + if (!dev->is_em25xx)
> > + fmt |= 0x20;
> > + /*
> > + * NOTE: it's not clear if this is really needed !
> > + * The datasheets say bit 5 is a reserved bit and devices seem to work
> > + * fine without it. But the Windows driver sets it for em2710/50+em28xx
> > + * devices and we've always been setting it, too.
> > + *
> > + * em2765 (em25xx, em276x/7x/8x) devices do NOT work with this bit set,
> > + * it's likely used for an additional (compressed ?) format there.
> > + */
> > + ret = em28xx_write_reg(dev, EM28XX_R27_OUTFMT, fmt);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
> > + if (ret < 0)
> > + return ret;
> > +
> > + vinctrl = dev->vinctl;
> > + if (em28xx_vbi_supported(dev) == 1) {
> > + vinctrl |= EM28XX_VINCTRL_VBI_RAW;
> > + em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
> > + em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
> > + em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
> > + if (dev->norm & V4L2_STD_525_60) {
> > + /* NTSC */
> > + em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
> > + } else if (dev->norm & V4L2_STD_625_50) {
> > + /* PAL */
> > + em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
> > + }
> > + }
> > +
> > + return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
> > +}
> > +
> > +static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
> > + u8 ymin, u8 ymax)
> > +{
> > + em28xx_videodbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
> > + xmin, ymin, xmax, ymax);
> > +
> > + em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
> > + em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
> > + em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
> > + return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
> > +}
> > +
> > +static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
> > + u16 width, u16 height)
> > +{
> > + u8 cwidth = width >> 2;
> > + u8 cheight = height >> 2;
> > + u8 overflow = (height >> 9 & 0x02) | (width >> 10 & 0x01);
> > + /* NOTE: size limit: 2047x1023 = 2MPix */
> > +
> > + em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
> > + hstart, vstart,
> > + ((overflow & 2) << 9 | cwidth << 2),
> > + ((overflow & 1) << 10 | cheight << 2));
> > +
> > + em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
> > + em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
> > + em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
> > + em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
> > + em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
> > +
> > + /* FIXME: function/meaning of these registers ? */
> > + /* FIXME: align width+height to multiples of 4 ?! */
> > + if (dev->is_em25xx) {
> > + em28xx_write_reg(dev, 0x34, width >> 4);
> > + em28xx_write_reg(dev, 0x35, height >> 4);
> > + }
> > +}
> > +
> > +static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
> > +{
> > + u8 mode;
> > + /* the em2800 scaler only supports scaling down to 50% */
> > +
> > + if (dev->board.is_em2800) {
> > + mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
> > + } else {
> > + u8 buf[2];
> > +
> > + buf[0] = h;
> > + buf[1] = h >> 8;
> > + em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
> > +
> > + buf[0] = v;
> > + buf[1] = v >> 8;
> > + em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
> > + /* it seems that both H and V scalers must be active
> > + to work correctly */
> > + mode = (h || v) ? 0x30 : 0x00;
> > + }
> > + return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
> > +}
> > +
> > +/* FIXME: this only function read values from dev */
> > +int em28xx_resolution_set(struct em28xx *dev)
> > +{
> > + int width, height;
> > + width = norm_maxw(dev);
> > + height = norm_maxh(dev);
> > +
> > + /* Properly setup VBI */
> > + dev->vbi_width = 720;
> > + if (dev->norm & V4L2_STD_525_60)
> > + dev->vbi_height = 12;
> > + else
> > + dev->vbi_height = 18;
> > +
> > + em28xx_set_outfmt(dev);
> > +
> > + em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
> > +
> > + /* If we don't set the start position to 2 in VBI mode, we end up
> > + with line 20/21 being YUYV encoded instead of being in 8-bit
> > + greyscale. The core of the issue is that line 21 (and line 23 for
> > + PAL WSS) are inside of active video region, and as a result they
> > + get the pixelformatting associated with that area. So by cropping
> > + it out, we end up with the same format as the rest of the VBI
> > + region */
> > + if (em28xx_vbi_supported(dev) == 1)
> > + em28xx_capture_area_set(dev, 0, 2, width, height);
> > + else
> > + em28xx_capture_area_set(dev, 0, 0, width, height);
> > +
> > + return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
> > +}
> > +
> > +int em28xx_vbi_supported(struct em28xx *dev)
> > +{
> > + /* Modprobe option to manually disable */
> > + if (disable_vbi == 1)
> > + return 0;
> > +
> > + if (dev->board.is_webcam)
> > + return 0;
> > +
> > + /* FIXME: check subdevices for VBI support */
> > +
> > + if (dev->chip_id == CHIP_ID_EM2860 ||
> > + dev->chip_id == CHIP_ID_EM2883)
> > + return 1;
> > +
> > + /* Version of em28xx that does not support VBI */
> > + return 0;
> > +}
> > +
> > +/* Set USB alternate setting for analog video */
> > +int em28xx_set_alternate(struct em28xx *dev)
> > +{
> > + int errCode;
> > + int i;
> > + unsigned int min_pkt_size = dev->width * 2 + 4;
> > +
> > + /* NOTE: for isoc transfers, only alt settings > 0 are allowed
> > + bulk transfers seem to work only with alt=0 ! */
> > + dev->alt = 0;
> > + if ((alt > 0) && (alt < dev->num_alt)) {
> > + em28xx_videodbg("alternate forced to %d\n", dev->alt);
> > + dev->alt = alt;
> > + goto set_alt;
> > + }
> > + if (dev->analog_xfer_bulk)
> > + goto set_alt;
> > +
> > + /* When image size is bigger than a certain value,
> > + the frame size should be increased, otherwise, only
> > + green screen will be received.
> > + */
> > + if (dev->width * 2 * dev->height > 720 * 240 * 2)
> > + min_pkt_size *= 2;
> > +
> > + for (i = 0; i < dev->num_alt; i++) {
> > + /* stop when the selected alt setting offers enough bandwidth */
> > + if (dev->alt_max_pkt_size_isoc[i] >= min_pkt_size) {
> > + dev->alt = i;
> > + break;
> > + /* otherwise make sure that we end up with the maximum bandwidth
> > + because the min_pkt_size equation might be wrong...
> > + */
> > + } else if (dev->alt_max_pkt_size_isoc[i] >
> > + dev->alt_max_pkt_size_isoc[dev->alt])
> > + dev->alt = i;
> > + }
> > +
> > +set_alt:
> > + /* NOTE: for bulk transfers, we need to call usb_set_interface()
> > + * even if the previous settings were the same. Otherwise streaming
> > + * fails with all urbs having status = -EOVERFLOW ! */
> > + if (dev->analog_xfer_bulk) {
> > + dev->max_pkt_size = 512; /* USB 2.0 spec */
> > + dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
> > + } else { /* isoc */
> > + em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
> > + min_pkt_size, dev->alt);
> > + dev->max_pkt_size =
> > + dev->alt_max_pkt_size_isoc[dev->alt];
> > + dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
> > + }
> > + em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
> > + dev->alt, dev->max_pkt_size);
> > + errCode = usb_set_interface(dev->udev, 0, dev->alt);
> > + if (errCode < 0) {
> > + em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
> > + dev->alt, errCode);
> > + return errCode;
> > + }
> > + return 0;
> > +}
> > +
> > /* ------------------------------------------------------------------
> > DMA and thread functions
> > ------------------------------------------------------------------*/
> > @@ -1817,6 +2076,113 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
> > return vfd;
> > }
> >
> > +static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
> > +{
> > + memset(ctl, 0, sizeof(*ctl));
> > +
> > + ctl->fname = XC2028_DEFAULT_FIRMWARE;
> > + ctl->max_len = 64;
> > + ctl->mts = em28xx_boards[dev->model].mts_firmware;
> > +
> > + switch (dev->model) {
> > + case EM2880_BOARD_EMPIRE_DUAL_TV:
> > + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
> > + case EM2882_BOARD_TERRATEC_HYBRID_XS:
> > + ctl->demod = XC3028_FE_ZARLINK456;
> > + break;
> > + case EM2880_BOARD_TERRATEC_HYBRID_XS:
> > + case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
> > + case EM2881_BOARD_PINNACLE_HYBRID_PRO:
> > + ctl->demod = XC3028_FE_ZARLINK456;
> > + break;
> > + case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
> > + case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
> > + ctl->demod = XC3028_FE_DEFAULT;
> > + break;
> > + case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
> > + ctl->demod = XC3028_FE_DEFAULT;
> > + ctl->fname = XC3028L_DEFAULT_FIRMWARE;
> > + break;
> > + case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
> > + case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
> > + case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
> > + /* FIXME: Better to specify the needed IF */
> > + ctl->demod = XC3028_FE_DEFAULT;
> > + break;
> > + case EM2883_BOARD_KWORLD_HYBRID_330U:
> > + case EM2882_BOARD_DIKOM_DK300:
> > + case EM2882_BOARD_KWORLD_VS_DVBT:
> > + ctl->demod = XC3028_FE_CHINA;
> > + ctl->fname = XC2028_DEFAULT_FIRMWARE;
> > + break;
> > + case EM2882_BOARD_EVGA_INDTUBE:
> > + ctl->demod = XC3028_FE_CHINA;
> > + ctl->fname = XC3028L_DEFAULT_FIRMWARE;
> > + break;
> > + default:
> > + ctl->demod = XC3028_FE_OREN538;
> > + }
> > +}
> > +
> > +void em28xx_tuner_setup(struct em28xx *dev)
> > +{
> > + struct tuner_setup tun_setup;
> > + struct v4l2_frequency f;
> > +
> > + if (dev->tuner_type == TUNER_ABSENT)
> > + return;
> > +
> > + memset(&tun_setup, 0, sizeof(tun_setup));
> > +
> > + tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
> > + tun_setup.tuner_callback = em28xx_tuner_callback;
> > +
> > + if (dev->board.radio.type) {
> > + tun_setup.type = dev->board.radio.type;
> > + tun_setup.addr = dev->board.radio_addr;
> > +
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
> > + }
> > +
> > + if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
> > + tun_setup.type = dev->tuner_type;
> > + tun_setup.addr = dev->tuner_addr;
> > +
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
> > + }
> > +
> > + if (dev->tda9887_conf) {
> > + struct v4l2_priv_tun_config tda9887_cfg;
> > +
> > + tda9887_cfg.tuner = TUNER_TDA9887;
> > + tda9887_cfg.priv = &dev->tda9887_conf;
> > +
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
> > + }
> > +
> > + if (dev->tuner_type == TUNER_XC2028) {
> > + struct v4l2_priv_tun_config xc2028_cfg;
> > + struct xc2028_ctrl ctl;
> > +
> > + memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
> > + memset(&ctl, 0, sizeof(ctl));
> > +
> > + em28xx_setup_xc3028(dev, &ctl);
> > +
> > + xc2028_cfg.tuner = TUNER_XC2028;
> > + xc2028_cfg.priv = &ctl;
> > +
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
> > + }
> > +
> > + /* configure tuner */
> > + f.tuner = 0;
> > + f.type = V4L2_TUNER_ANALOG_TV;
> > + f.frequency = 9076; /* just a magic number */
> > + dev->ctl_freq = f.frequency;
> > + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
> > +}
> > +
> > int em28xx_register_analog_devices(struct em28xx *dev)
> > {
> > u8 val;
> > diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
> > index 191ef3593891..0259270dda46 100644
> > --- a/drivers/media/usb/em28xx/em28xx.h
> > +++ b/drivers/media/usb/em28xx/em28xx.h
> > @@ -748,6 +748,7 @@ void em28xx_init_extension(struct em28xx *dev);
> > void em28xx_close_extension(struct em28xx *dev);
> >
> > /* Provided by em28xx-video.c */
> > +void em28xx_tuner_setup(struct em28xx *dev);
> > int em28xx_vb2_setup(struct em28xx *dev);
> > int em28xx_register_analog_devices(struct em28xx *dev);
> > void em28xx_release_analog_resources(struct em28xx *dev);
>
> Reviewed-by: Frank Schäfer <fschaefer.oss@googlemail.com>
>
I'll apply this and the other already reviewed patches. I'll eventually
move the order of em28xx_vbi_supported() on this changeset, keeping your
reviewed by, due to the comments you wrote on patch 4/22, putting it
to be before em28xx_wake_i2c().
--
Cheers,
Mauro
next prev parent reply other threads:[~2014-01-05 13:28 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-04 10:55 [PATCH v4 00/22] em28xx: split analog part into a separate module Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 01/22] [media] em28xx: move some video-specific functions to em28xx-video Mauro Carvalho Chehab
2014-01-05 10:11 ` Frank Schäfer
2014-01-05 13:28 ` Mauro Carvalho Chehab [this message]
2014-01-04 10:55 ` [PATCH v4 02/22] [media] em28xx: some cosmetic changes Mauro Carvalho Chehab
2014-01-05 10:13 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 03/22] [media] em28xx: move analog-specific init to em28xx-video Mauro Carvalho Chehab
2014-01-05 10:26 ` Frank Schäfer
2014-01-05 14:40 ` Mauro Carvalho Chehab
2014-01-06 21:28 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 04/22] [media] em28xx: make em28xx-video to be a separate module Mauro Carvalho Chehab
2014-01-05 10:47 ` Frank Schäfer
2014-01-05 12:56 ` Mauro Carvalho Chehab
2014-01-05 15:18 ` Mauro Carvalho Chehab
2014-01-06 21:35 ` Frank Schäfer
2014-01-06 17:38 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 05/22] [media] em28xx: initialize analog I2C devices at the right place Mauro Carvalho Chehab
2014-01-05 10:48 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 06/22] [media] em28xx: add warn messages for timeout Mauro Carvalho Chehab
2014-01-05 10:51 ` Frank Schäfer
2014-01-05 13:05 ` Mauro Carvalho Chehab
2014-01-05 13:25 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 07/22] [media] em28xx: improve extension information messages Mauro Carvalho Chehab
2014-01-05 10:55 ` Frank Schäfer
2014-01-05 13:08 ` Mauro Carvalho Chehab
2014-01-05 15:31 ` Mauro Carvalho Chehab
2014-01-06 17:44 ` Frank Schäfer
2014-01-06 18:17 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 08/22] [media] em28xx: convert i2c wait completion logic to use jiffies Mauro Carvalho Chehab
2014-01-05 11:03 ` Frank Schäfer
2014-01-05 13:10 ` Mauro Carvalho Chehab
2014-01-06 17:48 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 09/22] [media] tvp5150: make read operations atomic Mauro Carvalho Chehab
2014-01-05 11:07 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 10/22] [media] tuner-xc2028: remove unused code Mauro Carvalho Chehab
2014-01-05 11:07 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 11/22] [media] em28xx: check if a device has audio earlier Mauro Carvalho Chehab
2014-01-05 11:12 ` Frank Schäfer
2014-01-05 13:22 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 12/22] [media] em28xx: properly implement AC97 wait code Mauro Carvalho Chehab
2014-01-05 11:19 ` Frank Schäfer
2014-01-05 13:20 ` Mauro Carvalho Chehab
2014-01-05 15:44 ` Mauro Carvalho Chehab
2014-01-07 16:50 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 13/22] [media] em28xx: initialize audio latter Mauro Carvalho Chehab
2014-01-05 11:29 ` Frank Schäfer
2014-01-05 13:17 ` Mauro Carvalho Chehab
2014-01-07 17:00 ` Frank Schäfer
2014-01-08 14:29 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 14/22] [media] em28xx: unify module version Mauro Carvalho Chehab
2014-01-05 11:33 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 15/22] [media] em28xx: Fix em28xx deplock Mauro Carvalho Chehab
2014-01-05 11:38 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 16/22] [media] em28xx: use a better value for I2C timeouts Mauro Carvalho Chehab
2014-01-05 20:38 ` Frank Schäfer
2014-01-05 20:57 ` Mauro Carvalho Chehab
2014-01-07 17:15 ` Frank Schäfer
2014-01-08 14:39 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 17/22] [media] em28xx-i2c: Fix error code for I2C error transfers Mauro Carvalho Chehab
2014-01-05 20:40 ` Frank Schäfer
2014-01-06 9:55 ` Mauro Carvalho Chehab
2014-01-07 17:28 ` Frank Schäfer
2014-01-08 11:55 ` Mauro Carvalho Chehab
2014-01-08 19:37 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 18/22] [media] em28xx: don't return -ENODEV for I2C xfer errors Mauro Carvalho Chehab
2014-01-05 20:49 ` Frank Schäfer
2014-01-06 10:37 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 19/22] [media] em28xx: cleanup I2C debug messages Mauro Carvalho Chehab
2014-01-05 20:54 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 20/22] [media] em28xx: use usb_alloc_coherent() for audio Mauro Carvalho Chehab
2014-01-05 20:57 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 21/22] [media] em28xx-audio: allocate URBs at device driver init Mauro Carvalho Chehab
2014-01-05 21:02 ` Frank Schäfer
2014-01-05 21:25 ` Mauro Carvalho Chehab
2014-01-06 16:25 ` Mauro Carvalho Chehab
2014-01-07 17:03 ` Frank Schäfer
2014-01-08 14:10 ` Mauro Carvalho Chehab
2014-01-08 19:14 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 22/22] [media] em28xx: retry read operation if it fails Mauro Carvalho Chehab
2014-01-05 21:06 ` Frank Schäfer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140105112845.71a44854@samsung.com \
--to=m.chehab@samsung.com \
--cc=fschaefer.oss@googlemail.com \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).