[PATCH v3] usbtv: Enforce standard for color decoding
Depending on the chosen standard, configure the decoder to use the appropriate color encoding standard (PAL-like, NTSC-like or SECAM). Until now, the decoder was not configured for a specific color standard, making it autodetect the color encoding. While this may sound fine, it potentially causes the wrong image tuning parameters to be applied (e.g. tuning parameters for NTSC are applied to a PAL source), and may confuse users about what the actual standard is in use. This commit explicitly configures the color standard the decoder will use, making it visually obvious if a wrong standard was chosen. Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 45 --- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 6cad50d1e5f8..767fab1cc5cf 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -121,6 +121,25 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) return ret; } +static uint16_t usbtv_norm_to_16f_reg(v4l2_std_id norm) +{ + /* NTSC M/M-JP/M-KR */ + if (norm & V4L2_STD_NTSC) + return 0x00b8; + /* PAL BG/DK/H/I */ + if (norm & V4L2_STD_PAL) + return 0x00ee; + /* SECAM B/D/G/H/K/K1/L/Lc */ + if (norm & V4L2_STD_SECAM) + return 0x00ff; + if (norm & V4L2_STD_NTSC_443) + return 0x00a8; + if (norm & (V4L2_STD_PAL_M | V4L2_STD_PAL_60)) + return 0x00bc; + /* Fallback to automatic detection for other standards */ + return 0x; +} + static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { int ret; @@ -154,7 +173,7 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0263, 0x0017 }, { USBTV_BASE + 0x0266, 0x0016 }, { USBTV_BASE + 0x0267, 0x0036 }, - /* Epilog */ + /* End image tuning */ { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -182,7 +201,7 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0263, 0x001c }, { USBTV_BASE + 0x0266, 0x0011 }, { USBTV_BASE + 0x0267, 0x0005 }, - /* Epilog */ + /* End image tuning */ { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -210,7 +229,7 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0263, 0x0021 }, { USBTV_BASE + 0x0266, 0x0016 }, { USBTV_BASE + 0x0267, 0x0036 }, - /* Epilog */ + /* End image tuning */ { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -218,12 +237,28 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) ret = usbtv_configure_for_norm(usbtv, norm); if (!ret) { - if (norm & V4L2_STD_525_60) + /* Masks for norms using a NTSC or PAL color encoding. */ + static const v4l2_std_id ntsc_mask = + V4L2_STD_NTSC | V4L2_STD_NTSC_443; + static const v4l2_std_id pal_mask = + V4L2_STD_PAL | V4L2_STD_PAL_60 | V4L2_STD_PAL_M; + + if (norm & ntsc_mask) ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); - else if (norm & V4L2_STD_PAL) + else if (norm & pal_mask) ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); else if (norm & V4L2_STD_SECAM) ret = usbtv_set_regs(usbtv, secam, ARRAY_SIZE(secam)); + else + ret = -EINVAL; + } + + if (!ret) { + /* Configure the decoder for the color standard */ + const u16 cfg[][2] = { + { USBTV_BASE + 0x016f, usbtv_norm_to_16f_reg(norm) } + }; + ret = usbtv_set_regs(usbtv, cfg, ARRAY_SIZE(cfg)); } return ret; -- 2.17.0
[PATCH v2 4/6] usbtv: Keep norm parameter specific
The user-supplied norm value gets overwritten by the generic .norm member from the norm_params. That way, we lose the specific norm the user may want to set. For instance, if the user specifies V4L2_STD_PAL_60, the value actually used will be V4L2_STD_525_60, which in the end will be as if the user had specified V4L2_STD_NTSC, since this is always the first bitfield we match the norm value against before configuring the hardware. The norm_params array is only there to match a norm with an output resolution. The norm value itself should not be changed. Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 29e245083247..6cad50d1e5f8 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -77,7 +77,7 @@ static int usbtv_configure_for_norm(struct usbtv *usbtv, v4l2_std_id norm) usbtv->height = params->cap_height; usbtv->n_chunks = usbtv->width * usbtv->height / 4 / USBTV_CHUNK; - usbtv->norm = params->norm; + usbtv->norm = norm; } else ret = -EINVAL; -- 2.17.0
[PATCH v2 5/6] usbtv: Enforce standard for color decoding
Depending on the chosen standard, configure the decoder to use the appropriate color encoding standard (PAL-like, NTSC-like or SECAM). Until now, the decoder was not configured for a specific color standard, making it autodetect the color encoding. While this may sound fine, it potentially causes the wrong image tuning parameters to be applied (e.g. tuning parameters for NTSC are applied to a PAL source), and may confuse users about what the actual standard is in use. This commit explicitly configures the color standard the decoder will use, making it visually obvious if a wrong standard was chosen. Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 45 --- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 6cad50d1e5f8..d0bf5eb217b1 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -121,6 +121,25 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) return ret; } +static uint16_t usbtv_norm_to_16f_reg(v4l2_std_id norm) +{ + /* NTSC M/M-JP/M-KR */ + if (norm & V4L2_STD_NTSC) + return 0x00b8; + /* PAL BG/DK/H/I */ + if (norm & V4L2_STD_PAL) + return 0x00ee; + /* SECAM B/D/G/H/K/K1/L/Lc */ + if (norm & V4L2_STD_SECAM) + return 0x00ff; + if (norm & V4L2_STD_NTSC_443) + return 0x00a8; + if (norm & (V4L2_STD_PAL_M | V4L2_STD_PAL_60)) + return 0x00bc; + /* Fallback to automatic detection for other standards */ + return 0x; +} + static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { int ret; @@ -154,7 +173,7 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0263, 0x0017 }, { USBTV_BASE + 0x0266, 0x0016 }, { USBTV_BASE + 0x0267, 0x0036 }, - /* Epilog */ + /* End image tuning */ { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -182,7 +201,7 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0263, 0x001c }, { USBTV_BASE + 0x0266, 0x0011 }, { USBTV_BASE + 0x0267, 0x0005 }, - /* Epilog */ + /* End image tuning */ { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -210,7 +229,7 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0263, 0x0021 }, { USBTV_BASE + 0x0266, 0x0016 }, { USBTV_BASE + 0x0267, 0x0036 }, - /* Epilog */ + /* End image tuning */ { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, }; @@ -218,12 +237,28 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) ret = usbtv_configure_for_norm(usbtv, norm); if (!ret) { - if (norm & V4L2_STD_525_60) + /* Masks for norms using a NTSC or PAL color encoding. */ + static const v4l2_std_id ntsc_mask = + V4L2_STD_NTSC | V4L2_STD_NTSC_443; + static const v4l2_std_id pal_mask = + V4L2_STD_PAL | V4L2_STD_PAL_60 | V4L2_STD_PAL_M; + + if (norm & ntsc_mask) ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); - else if (norm & V4L2_STD_PAL) + else if (norm & pal_mask) ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); else if (norm & V4L2_STD_SECAM) ret = usbtv_set_regs(usbtv, secam, ARRAY_SIZE(secam)); + else + ret = -EINVAL; + } + + if (!ret) { + /* Configure the decoder for the color standard */ + u16 cfg[][2] = { + { USBTV_BASE + 0x016f, usbtv_norm_to_16f_reg(norm) } + }; + ret = usbtv_set_regs(usbtv, cfg, ARRAY_SIZE(cfg)); } return ret; -- 2.17.0
[PATCH v2 2/6] usbtv: Add SECAM support
Add support for the SECAM norm, using the "AVSECAM" decoder configuration sequence found in Windows driver's .INF file. For reference, the "AVSECAM" sequence in the .INF file is: 0x04,0x73,0xDC,0x72,0xA2,0x90,0x35,0x01,0x30,0x04,0x08,0x2D,0x28,0x08, 0x02,0x69,0x16,0x35,0x21,0x16,0x36 Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 38 ++- drivers/media/usb/usbtv/usbtv.h | 2 +- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 97f9790954f9..6b0a10173388 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -57,6 +57,11 @@ static struct usbtv_norm_params norm_params[] = { .norm = V4L2_STD_PAL, .cap_width = 720, .cap_height = 576, + }, + { + .norm = V4L2_STD_SECAM, + .cap_width = 720, + .cap_height = 576, } }; @@ -187,6 +192,34 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x024f, 0x0002 }, }; + static const u16 secam[][2] = { + /* "AVSECAM" tuning sequence from .INF file */ + { USBTV_BASE + 0x0003, 0x0004 }, + { USBTV_BASE + 0x001a, 0x0073 }, + { USBTV_BASE + 0x0100, 0x00dc }, + { USBTV_BASE + 0x010e, 0x0072 }, + { USBTV_BASE + 0x010f, 0x00a2 }, + { USBTV_BASE + 0x0112, 0x0090 }, + { USBTV_BASE + 0x0115, 0x0035 }, + { USBTV_BASE + 0x0117, 0x0001 }, + { USBTV_BASE + 0x0118, 0x0030 }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002d }, + { USBTV_BASE + 0x0225, 0x0028 }, + { USBTV_BASE + 0x024e, 0x0008 }, + { USBTV_BASE + 0x024f, 0x0002 }, + { USBTV_BASE + 0x0254, 0x0069 }, + { USBTV_BASE + 0x025a, 0x0016 }, + { USBTV_BASE + 0x025b, 0x0035 }, + { USBTV_BASE + 0x0263, 0x0021 }, + { USBTV_BASE + 0x0266, 0x0016 }, + { USBTV_BASE + 0x0267, 0x0036 }, + /* Epilog */ + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, + }; + ret = usbtv_configure_for_norm(usbtv, norm); if (!ret) { @@ -194,6 +227,8 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); else if (norm & V4L2_STD_PAL) ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); + else if (norm & V4L2_STD_SECAM) + ret = usbtv_set_regs(usbtv, secam, ARRAY_SIZE(secam)); } return ret; @@ -605,7 +640,8 @@ static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) int ret = -EINVAL; struct usbtv *usbtv = video_drvdata(file); - if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL)) + if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL) || + (norm & V4L2_STD_SECAM)) ret = usbtv_select_norm(usbtv, norm); return ret; diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 0231e449877e..77a368e90fd0 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -68,7 +68,7 @@ #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0xf000) >> 15) #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x0fff) -#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL) +#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL | V4L2_STD_SECAM) /* parameters for supported TV norms */ struct usbtv_norm_params { -- 2.17.0
[PATCH v2 6/6] usbtv: Use the constant for supported standards
Use the USBTV_TV_STD define instead of repeating ourselves. Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index d0bf5eb217b1..eda51dbf063b 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -670,8 +670,7 @@ static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) int ret = -EINVAL; struct usbtv *usbtv = video_drvdata(file); - if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL) || - (norm & V4L2_STD_SECAM)) + if (norm & USBTV_TV_STD) ret = usbtv_select_norm(usbtv, norm); return ret; -- 2.17.0
[PATCH v2 1/6] usbtv: Use same decoder sequence as Windows driver
Re-format the register {address, value} pairs so they follow the same order as the decoder configuration sequences in the Windows driver's .INF file. For instance, for PAL, the "AVPAL" sequence in the .INF file is: 0x04,0x68,0xD3,0x72,0xA2,0xB0,0x15,0x01,0x2C,0x10,0x20,0x2e,0x08,0x02, 0x02,0x59,0x16,0x35,0x17,0x16,0x36 Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 40 +++ 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 3668a04359e8..97f9790954f9 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -124,40 +124,67 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { int ret; + /* These are the series of register values used to configure the +* decoder for a specific standard. +* The first 21 register writes are copied from the +* Settings\DecoderDefaults registry keys present in the Windows driver +* .INF file, and control various image tuning parameters (color +* correction, sharpness, ...). +*/ static const u16 pal[][2] = { + /* "AVPAL" tuning sequence from .INF file */ + { USBTV_BASE + 0x0003, 0x0004 }, { USBTV_BASE + 0x001a, 0x0068 }, + { USBTV_BASE + 0x0100, 0x00d3 }, { USBTV_BASE + 0x010e, 0x0072 }, { USBTV_BASE + 0x010f, 0x00a2 }, { USBTV_BASE + 0x0112, 0x00b0 }, + { USBTV_BASE + 0x0115, 0x0015 }, { USBTV_BASE + 0x0117, 0x0001 }, { USBTV_BASE + 0x0118, 0x002c }, { USBTV_BASE + 0x012d, 0x0010 }, { USBTV_BASE + 0x012f, 0x0020 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, { USBTV_BASE + 0x0254, 0x0059 }, { USBTV_BASE + 0x025a, 0x0016 }, { USBTV_BASE + 0x025b, 0x0035 }, { USBTV_BASE + 0x0263, 0x0017 }, { USBTV_BASE + 0x0266, 0x0016 }, - { USBTV_BASE + 0x0267, 0x0036 } + { USBTV_BASE + 0x0267, 0x0036 }, + /* Epilog */ + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, }; static const u16 ntsc[][2] = { + /* "AVNTSC" tuning sequence from .INF file */ + { USBTV_BASE + 0x0003, 0x0004 }, { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x0100, 0x00d3 }, { USBTV_BASE + 0x010e, 0x0068 }, { USBTV_BASE + 0x010f, 0x009c }, { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0115, 0x0015 }, { USBTV_BASE + 0x0117, 0x }, { USBTV_BASE + 0x0118, 0x00fc }, { USBTV_BASE + 0x012d, 0x0004 }, { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0001 }, { USBTV_BASE + 0x0254, 0x005f }, { USBTV_BASE + 0x025a, 0x0012 }, { USBTV_BASE + 0x025b, 0x0001 }, { USBTV_BASE + 0x0263, 0x001c }, { USBTV_BASE + 0x0266, 0x0011 }, - { USBTV_BASE + 0x0267, 0x0005 } + { USBTV_BASE + 0x0267, 0x0005 }, + /* Epilog */ + { USBTV_BASE + 0x024e, 0x0002 }, + { USBTV_BASE + 0x024f, 0x0002 }, }; ret = usbtv_configure_for_norm(usbtv, norm); @@ -236,15 +263,6 @@ static int usbtv_setup_capture(struct usbtv *usbtv) { USBTV_BASE + 0x0158, 0x001f }, { USBTV_BASE + 0x0159, 0x0006 }, { USBTV_BASE + 0x015d, 0x }, - - { USBTV_BASE + 0x0003, 0x0004 }, - { USBTV_BASE + 0x0100, 0x00d3 }, - { USBTV_BASE + 0x0115, 0x0015 }, - { USBTV_BASE + 0x0220, 0x002e }, - { USBTV_BASE + 0x0225, 0x0008 }, - { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024f, 0x0002 }, }; ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup)); -- 2.17.0
[PATCH v2 3/6] usbtv: Use V4L2 defines to select capture resolution
Make use of the V4L2_STD_525_60 and V4L2_STD_625_50 defines to determine the vertical resolution to use when capturing. V4L2_STD_525_60 (resp. V4L2_STD_625_50) is the set of standards using 525 (resp. 625) lines per frame, independently of the color encoding. Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 7 +-- 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 6b0a10173388..29e245083247 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -54,12 +54,7 @@ static struct usbtv_norm_params norm_params[] = { .cap_height = 480, }, { - .norm = V4L2_STD_PAL, - .cap_width = 720, - .cap_height = 576, - }, - { - .norm = V4L2_STD_SECAM, + .norm = V4L2_STD_625_50, .cap_width = 720, .cap_height = 576, } -- 2.17.0
[PATCH v2 0/6] usbtv: Add SECAM support and fix color encoding selection
This series adds SECAM support to the usbtv driver, while also attempting to mimic the Windows driver's behavior regarding color encoding selection. I made USB captures of the device as it is set up by the Windows driver, for all the supported video standards. The analog source used is the composite output of a video card, which is configured to output a signal using the same standard as the one configured for the capture, when that is possible. This enabled me to find new values for the 0x016f register that I had missed in the v1, as well as test my patches. Unfortunately, I did not have a SECAM source for the tests, so they were limited to setting the standard to SECAM for a PAL source, and making sure the output was the same between the Windows and the Linux driver. The capture adapter used for the tests is a QSonic VG-310, with USB ID 1b71:3002. The Windows driver used as reference is EasyCap driver version 2.1.1.2 (2011-06-08). The changes since the v1 are: - the output resolution is selected independently of the color encoding. For instance, PAL-M, while using a PAL-like color encoding, has the same resolution as NTSC-M, so the NTSC resolution will be used in that case - conversely, the color encoding is configured independently of the resolution - PAL and NTSC variants have a different value for register 0x016f - the norm value set by the user is no longer overwritten by the driver with a generic value when selecting the output resolution, so specific standards (e.g. NTSC-443) can actually be selected - minor cosmetic changes Hugo Grostabussiat (6): usbtv: Use same decoder sequence as Windows driver usbtv: Add SECAM support usbtv: Use V4L2 defines to select capture resolution usbtv: Keep norm parameter specific usbtv: Enforce standard for color decoding usbtv: Use the constant for supported standards drivers/media/usb/usbtv/usbtv-video.c | 115 ++ drivers/media/usb/usbtv/usbtv.h | 2 +- 2 files changed, 100 insertions(+), 17 deletions(-) -- 2.17.0
[PATCH 1/2] usbtv: Use same decoder sequence as Windows driver
Re-format the register {address, value} pairs so they follow the same order as the decoder configuration sequences in the Windows driver's .INF file. For instance, for PAL, the "AVPAL" sequence in the .INF file is: 0x04,0x68,0xD3,0x72,0xA2,0xB0,0x15,0x01,0x2C,0x10,0x20,0x2e,0x08,0x02, 0x02,0x59,0x16,0x35,0x17,0x16,0x36 Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 26 +- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 3668a04359e8..52d06b30fabb 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -124,15 +124,26 @@ static int usbtv_select_input(struct usbtv *usbtv, int input) static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { int ret; + /* These are the series of register values used to configure the +* decoder for a specific standard. +* They are copied from the Settings\DecoderDefaults registry keys +* present in the Windows driver .INF file for each norm. +*/ static const u16 pal[][2] = { + { USBTV_BASE + 0x0003, 0x0004 }, { USBTV_BASE + 0x001a, 0x0068 }, + { USBTV_BASE + 0x0100, 0x00d3 }, { USBTV_BASE + 0x010e, 0x0072 }, { USBTV_BASE + 0x010f, 0x00a2 }, { USBTV_BASE + 0x0112, 0x00b0 }, + { USBTV_BASE + 0x0115, 0x0015 }, { USBTV_BASE + 0x0117, 0x0001 }, { USBTV_BASE + 0x0118, 0x002c }, { USBTV_BASE + 0x012d, 0x0010 }, { USBTV_BASE + 0x012f, 0x0020 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0002 }, { USBTV_BASE + 0x0254, 0x0059 }, { USBTV_BASE + 0x025a, 0x0016 }, @@ -143,14 +154,20 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) }; static const u16 ntsc[][2] = { + { USBTV_BASE + 0x0003, 0x0004 }, { USBTV_BASE + 0x001a, 0x0079 }, + { USBTV_BASE + 0x0100, 0x00d3 }, { USBTV_BASE + 0x010e, 0x0068 }, { USBTV_BASE + 0x010f, 0x009c }, { USBTV_BASE + 0x0112, 0x00f0 }, + { USBTV_BASE + 0x0115, 0x0015 }, { USBTV_BASE + 0x0117, 0x }, { USBTV_BASE + 0x0118, 0x00fc }, { USBTV_BASE + 0x012d, 0x0004 }, { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002e }, + { USBTV_BASE + 0x0225, 0x0008 }, + { USBTV_BASE + 0x024e, 0x0002 }, { USBTV_BASE + 0x024f, 0x0001 }, { USBTV_BASE + 0x0254, 0x005f }, { USBTV_BASE + 0x025a, 0x0012 }, @@ -236,15 +253,6 @@ static int usbtv_setup_capture(struct usbtv *usbtv) { USBTV_BASE + 0x0158, 0x001f }, { USBTV_BASE + 0x0159, 0x0006 }, { USBTV_BASE + 0x015d, 0x }, - - { USBTV_BASE + 0x0003, 0x0004 }, - { USBTV_BASE + 0x0100, 0x00d3 }, - { USBTV_BASE + 0x0115, 0x0015 }, - { USBTV_BASE + 0x0220, 0x002e }, - { USBTV_BASE + 0x0225, 0x0008 }, - { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024e, 0x0002 }, - { USBTV_BASE + 0x024f, 0x0002 }, }; ret = usbtv_set_regs(usbtv, setup, ARRAY_SIZE(setup)); -- 2.16.2
[PATCH 2/2] usbtv: Add SECAM support
Add support for the SECAM norm, using the "AVSECAM" decoder configuration sequence found in Windows driver's .INF file. For reference, the "AVSECAM" sequence in the .INF file is: 0x04,0x73,0xDC,0x72,0xA2,0x90,0x35,0x01,0x30,0x04,0x08,0x2D,0x28,0x08, 0x02,0x69,0x16,0x35,0x21,0x16,0x36 Signed-off-by: Hugo Grostabussiat --- drivers/media/usb/usbtv/usbtv-video.c | 34 +- drivers/media/usb/usbtv/usbtv.h | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 52d06b30fabb..7dd4f25203db 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -57,6 +57,11 @@ static struct usbtv_norm_params norm_params[] = { .norm = V4L2_STD_PAL, .cap_width = 720, .cap_height = 576, + }, + { + .norm = V4L2_STD_SECAM, + .cap_width = 720, + .cap_height = 576, } }; @@ -177,6 +182,30 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) { USBTV_BASE + 0x0267, 0x0005 } }; + static const u16 secam[][2] = { + { USBTV_BASE + 0x0003, 0x0004 }, + { USBTV_BASE + 0x001a, 0x0073 }, + { USBTV_BASE + 0x0100, 0x00dc }, + { USBTV_BASE + 0x010e, 0x0072 }, + { USBTV_BASE + 0x010f, 0x00a2 }, + { USBTV_BASE + 0x0112, 0x0090 }, + { USBTV_BASE + 0x0115, 0x0035 }, + { USBTV_BASE + 0x0117, 0x0001 }, + { USBTV_BASE + 0x0118, 0x0030 }, + { USBTV_BASE + 0x012d, 0x0004 }, + { USBTV_BASE + 0x012f, 0x0008 }, + { USBTV_BASE + 0x0220, 0x002d }, + { USBTV_BASE + 0x0225, 0x0028 }, + { USBTV_BASE + 0x024e, 0x0008 }, + { USBTV_BASE + 0x024f, 0x0002 }, + { USBTV_BASE + 0x0254, 0x0069 }, + { USBTV_BASE + 0x025a, 0x0016 }, + { USBTV_BASE + 0x025b, 0x0035 }, + { USBTV_BASE + 0x0263, 0x0021 }, + { USBTV_BASE + 0x0266, 0x0016 }, + { USBTV_BASE + 0x0267, 0x0036 } + }; + ret = usbtv_configure_for_norm(usbtv, norm); if (!ret) { @@ -184,6 +213,8 @@ static int usbtv_select_norm(struct usbtv *usbtv, v4l2_std_id norm) ret = usbtv_set_regs(usbtv, ntsc, ARRAY_SIZE(ntsc)); else if (norm & V4L2_STD_PAL) ret = usbtv_set_regs(usbtv, pal, ARRAY_SIZE(pal)); + else if (norm & V4L2_STD_SECAM) + ret = usbtv_set_regs(usbtv, secam, ARRAY_SIZE(secam)); } return ret; @@ -595,7 +626,8 @@ static int usbtv_s_std(struct file *file, void *priv, v4l2_std_id norm) int ret = -EINVAL; struct usbtv *usbtv = video_drvdata(file); - if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL)) + if ((norm & V4L2_STD_525_60) || (norm & V4L2_STD_PAL) || + (norm & V4L2_STD_SECAM)) ret = usbtv_select_norm(usbtv, norm); return ret; diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 0231e449877e..77a368e90fd0 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -68,7 +68,7 @@ #define USBTV_ODD(chunk) ((be32_to_cpu(chunk[0]) & 0xf000) >> 15) #define USBTV_CHUNK_NO(chunk) (be32_to_cpu(chunk[0]) & 0x0fff) -#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL) +#define USBTV_TV_STD (V4L2_STD_525_60 | V4L2_STD_PAL | V4L2_STD_SECAM) /* parameters for supported TV norms */ struct usbtv_norm_params { -- 2.16.2
[PATCH 0/2] usbtv: Add SECAM support
This patch series adds support for the SECAM standard to the USBTV video grabber driver. The first patch prepares for the inclusion of further decoder configuration sequences by making them follow the same order and length as the sequences which can be found inside the Windows driver's .INF file. The second patch adds the SECAM decoder configuration sequence found in the .INF file, and exposes SECAM support to userspace. Hugo Grostabussiat (2): usbtv: Use same decoder sequence as Windows driver usbtv: Add SECAM support drivers/media/usb/usbtv/usbtv-video.c | 60 +-- drivers/media/usb/usbtv/usbtv.h | 2 +- 2 files changed, 51 insertions(+), 11 deletions(-) -- 2.16.2