From: "Frank Schäfer" <fschaefer.oss@googlemail.com>
To: Mauro Carvalho Chehab <m.chehab@samsung.com>, unlisted-recipients:;
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:11:20 +0100 [thread overview]
Message-ID: <52C92FC8.1060801@googlemail.com> (raw)
In-Reply-To: <1388832951-11195-2-git-send-email-m.chehab@samsung.com>
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>
next prev parent reply other threads:[~2014-01-05 10:10 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 [this message]
2014-01-05 13:28 ` Mauro Carvalho Chehab
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=52C92FC8.1060801@googlemail.com \
--to=fschaefer.oss@googlemail.com \
--cc=linux-media@vger.kernel.org \
--cc=m.chehab@samsung.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.