XC4000: added firmware_name parameter
The firmware_name module parameter makes it possible to set the firmware file name. It defaults to xc4000.fw if not specified. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-03 17:14:59.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 12:29:31.0 +0200 @@ -47,16 +47,20 @@ \t\t1 keep device energized and with tuner ready all the times.\n \t\tFaster, but consumes more power and keeps the device hotter); +#define XC4000_DEFAULT_FIRMWARE xc4000.fw + +static char firmware_name[30]; +module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); +MODULE_PARM_DESC(firmware_name, \n\t\tFirmware file name. Allows overriding + the default firmware\n + \t\tname.); + static DEFINE_MUTEX(xc4000_list_mutex); static LIST_HEAD(hybrid_tuner_instance_list); #define dprintk(level, fmt, arg...) if (debug = level) \ printk(KERN_INFO %s: fmt, xc4000, ## arg) -/* Note that the last version digit is my internal build number (so I can - rev the firmware even if the core Xceive firmware was unchanged) */ -#define XC4000_DEFAULT_FIRMWARE dvb-fe-xc4000-1.4.1.fw - /* struct for storing firmware table */ struct firmware_description { unsigned int type; @@ -714,7 +718,10 @@ char name[33]; const char *fname; - fname = XC4000_DEFAULT_FIRMWARE; + if (firmware_name[0] != '\0') + fname = firmware_name; + else + fname = XC4000_DEFAULT_FIRMWARE; printk(Reading firmware %s\n, fname); rc = request_firmware(fw, fname, priv-i2c_props.adap-dev.parent);
XC4000: simplified seek_firmware()
This patch simplifies the code in seek_firmware(). Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 12:50:41.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 13:10:00.0 +0200 @@ -606,8 +606,8 @@ v4l2_std_id *id) { struct xc4000_priv *priv = fe-tuner_priv; - int i, best_i = -1, best_nr_matches = 0; - unsigned inttype_mask = 0; + int i, best_i = -1; + unsigned int best_nr_diffs = 255U; if (!priv-firm) { printk(Error! firmware not loaded\n); @@ -617,63 +617,42 @@ if (((type ~SCODE) == 0) (*id == 0)) *id = V4L2_STD_PAL; - if (type BASE) - type_mask = BASE_TYPES; - else if (type SCODE) { - type = SCODE_TYPES; - type_mask = SCODE_TYPES ~HAS_IF; - } else if (type DTV_TYPES) - type_mask = DTV_TYPES; - else if (type STD_SPECIFIC_TYPES) - type_mask = STD_SPECIFIC_TYPES; - - type = type_mask; - - if (!(type SCODE)) - type_mask = ~0; - - /* Seek for exact match */ - for (i = 0; i priv-firm_size; i++) { - if ((type == (priv-firm[i].type type_mask)) - (*id == priv-firm[i].id)) - goto found; - } - /* Seek for generic video standard match */ for (i = 0; i priv-firm_size; i++) { - v4l2_std_id match_mask; - int nr_matches; + v4l2_std_id id_diff_mask = + (priv-firm[i].id ^ (*id)) (*id); + unsigned int type_diff_mask = + (priv-firm[i].type ^ type) + (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE); + unsigned int nr_diffs; - if (type != (priv-firm[i].type type_mask)) + if (type_diff_mask + (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE)) continue; - match_mask = *id priv-firm[i].id; - if (!match_mask) - continue; - - if ((*id match_mask) == *id) - goto found; /* Supports all the requested standards */ + nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask); + if (!nr_diffs) /* Supports all the requested standards */ + goto found; - nr_matches = hweight64(match_mask); - if (nr_matches best_nr_matches) { - best_nr_matches = nr_matches; + if (nr_diffs best_nr_diffs) { + best_nr_diffs = nr_diffs; best_i = i; } } - if (best_nr_matches 0) { - printk(Selecting best matching firmware (%d bits) for - type=, best_nr_matches); + /* FIXME: Would make sense to seek for type hint match ? */ + if (best_i 0) { + i = -ENOENT; + goto ret; + } + + if (best_nr_diffs 0U) { + printk(Selecting best matching firmware (%u bits differ) for + type=, best_nr_diffs); printk((%x), id %016llx:\n, type, (unsigned long long)*id); i = best_i; - goto found; } - /*FIXME: Would make sense to seek for type hint match ? */ - - i = -ENOENT; - goto ret; - found: *id = priv-firm[i].id;
XC4000: simplified load_scode
Removed unused code from load_scode() (all SCODE firmwares are assumed to have the HAS_IF bit set). Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 13:10:37.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 13:19:55.0 +0200 @@ -781,8 +781,7 @@ p += sizeof(size); if (!size || size endp - p) { - printk(Firmware type ); - printk((%x), id %llx is corrupted + printk(Firmware type (%x), id %llx is corrupted (size=%d, expected %d)\n, type, (unsigned long long)id, (unsigned)(endp - p), size); @@ -840,10 +839,10 @@ v4l2_std_id *id, __u16 int_freq, int scode) { struct xc4000_priv *priv = fe-tuner_priv; - intpos, rc; - unsigned char *p; - u8 scode_buf[13]; - u8 indirect_mode[5]; + int pos, rc; + unsigned char *p; + u8 scode_buf[13]; + u8 indirect_mode[5]; dprintk(1, %s called int_freq=%d\n, __func__, int_freq); @@ -863,18 +862,9 @@ p = priv-firm[pos].ptr; - if (priv-firm[pos].type HAS_IF) { - if (priv-firm[pos].size != 12 * 16 || scode = 16) - return -EINVAL; - p += 12 * scode; - } else { - /* 16 SCODE entries per file; each SCODE entry is 12 bytes and - * has a 2-byte size header in the firmware format. */ - if (priv-firm[pos].size != 14 * 16 || scode = 16 || - le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12) - return -EINVAL; - p += 14 * scode + 2; - } + if (priv-firm[pos].size != 12 * 16 || scode = 16) + return -EINVAL; + p += 12 * scode; tuner_info(Loading SCODE for type=); dump_firm_type_and_int_freq(priv-firm[pos].type,
XC4000: check_firmware() cleanup
This patch makes the following fixes in check_firmware(): - there is only one BASE and INIT1 firmware for XC4000 - loading SCODE is needed also for FM radio Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 13:23:07.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 13:34:17.0 +0200 @@ -904,7 +904,7 @@ struct xc4000_priv *priv = fe-tuner_priv; struct firmware_properties new_fw; int rc = 0, is_retry = 0; - u16 version, hwmodel; + u16 version = 0, hwmodel; v4l2_std_id std0; u8 hw_major, hw_minor, fw_major, fw_minor; @@ -946,8 +946,7 @@ } /* No need to reload base firmware if it matches */ - if (((BASE | new_fw.type) BASE_TYPES) == - (priv-cur_fw.type BASE_TYPES)) { + if (priv-cur_fw.type BASE) { dprintk(1, BASE firmware not changed.\n); goto skip_base; } @@ -962,7 +961,7 @@ /* BASE firmwares are all std0 */ std0 = 0; - rc = load_firmware(fe, BASE | new_fw.type, std0); + rc = load_firmware(fe, BASE, std0); if (rc 0) { printk(Error %d while loading base firmware\n, rc); goto fail; @@ -971,10 +970,9 @@ /* Load INIT1, if needed */ dprintk(1, Load init1 firmware, if exists\n); - rc = load_firmware(fe, BASE | INIT1 | new_fw.type, std0); + rc = load_firmware(fe, BASE | INIT1, std0); if (rc == -ENOENT) - rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) ~F8MHZ, - std0); + rc = load_firmware(fe, BASE | INIT1, std0); if (rc 0 rc != -ENOENT) { tuner_err(Error %d while loading init1 firmware\n, rc); @@ -1008,9 +1006,6 @@ goto check_device; } - if (new_fw.type FM) - goto check_device; - /* Load SCODE firmware, if exists */ rc = load_scode(fe, new_fw.type | new_fw.scode_table, new_fw.id, new_fw.int_freq, new_fw.scode_nr);
XC4000: implemented power management
The following patch implements the xc4000_sleep() function. The 'no_powerdown' module parameter is now interpreted differently: - 0 uses a device-specific default - 1 disables power management like before - 2 enables power management Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 13:35:59.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 13:57:11.0 +0200 @@ -43,9 +43,11 @@ static int no_poweroff; module_param(no_poweroff, int, 0644); -MODULE_PARM_DESC(no_poweroff, 0 (default) powers device off when not used.\n - \t\t1 keep device energized and with tuner ready all the times.\n - \t\tFaster, but consumes more power and keeps the device hotter); +MODULE_PARM_DESC(no_poweroff, \n\t\t1: keep device energized and with tuner + ready all the times.\n + \t\tFaster, but consumes more power and keeps the device hotter.\n + \t\t2: powers device off when not used.\n + \t\t0 (default): use device-specific default mode.); #define XC4000_DEFAULT_FIRMWARE xc4000.fw @@ -102,6 +104,7 @@ /* Misc Defines */ #define MAX_TV_STANDARD 24 #define XC_MAX_I2C_WRITE_LENGTH 64 +#define XC_POWERED_DOWN 0x8000U /* Signal Types */ #define XC_RF_MODE_AIR 0 @@ -1365,8 +1368,34 @@ static int xc4000_sleep(struct dvb_frontend *fe) { - /* FIXME: djh disable this for now... */ - return XC_RESULT_SUCCESS; + struct xc4000_priv *priv = fe-tuner_priv; + int ret = XC_RESULT_SUCCESS; + + dprintk(1, %s()\n, __func__); + + mutex_lock(priv-lock); + + /* Avoid firmware reload on slow devices */ + if ((no_poweroff == 2 || + (no_poweroff == 0 + priv-card_type != XC4000_CARD_WINFAST_CX88)) + (priv-cur_fw.type BASE) != 0) { + /* force reset and firmware reload */ + priv-cur_fw.type = XC_POWERED_DOWN; + + if (xc_write_reg(priv, XREG_POWER_DOWN, 0) + != XC_RESULT_SUCCESS) { + printk(KERN_ERR + xc4000: %s() unable to shutdown tuner\n, + __func__); + ret = -EREMOTEIO; + } + xc_wait(20); + } + + mutex_unlock(priv-lock); + + return ret; } static int xc4000_init(struct dvb_frontend *fe)
XC4000: firmware initialization
This patch fixes/cleans up the loading of the firmware file when the driver is loaded and initialized. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 13:58:03.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 14:12:06.0 +0200 @@ -1400,21 +1400,8 @@ static int xc4000_init(struct dvb_frontend *fe) { - struct xc4000_priv *priv = fe-tuner_priv; - int ret; dprintk(1, %s()\n, __func__); - mutex_lock(priv-lock); - ret = check_firmware(fe, DTV8, 0, priv-if_khz); - mutex_unlock(priv-lock); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR xc4000: Unable to initialise tuner\n); - return -EREMOTEIO; - } - - if (debug) - xc_debug_dump(priv); - return 0; } @@ -1511,8 +1498,14 @@ instance of the driver has loaded the firmware. */ - if (xc4000_readreg(priv, XREG_PRODUCT_ID, id) != XC_RESULT_SUCCESS) + if (instance == 1) { + if (xc4000_readreg(priv, XREG_PRODUCT_ID, id) + != XC_RESULT_SUCCESS) goto fail; + } else { + id = ((priv-cur_fw.type BASE) != 0 ? + priv-hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED); + } switch (id) { case XC_PRODUCT_ID_FW_LOADED: @@ -1541,16 +1534,19 @@ memcpy(fe-ops.tuner_ops, xc4000_tuner_ops, sizeof(struct dvb_tuner_ops)); - /* FIXME: For now, load the firmware at startup. We will remove this - before the code goes to production... */ - mutex_lock(priv-lock); - check_firmware(fe, DTV8, 0, priv-if_khz); - mutex_unlock(priv-lock); + if (instance == 1) { + int ret; + mutex_lock(priv-lock); + ret = xc4000_fwupload(fe); + mutex_unlock(priv-lock); + if (ret != XC_RESULT_SUCCESS) + goto fail2; + } return fe; fail: mutex_unlock(xc4000_list_mutex); - +fail2: xc4000_release(fe); return NULL; }
XC4000: debug message improvements
The following patch makes a few minor changes to the printing of debug messages, and reporting the tuner status. The 'debug' module parameter can now be set from 0 to 2 to control the verbosity of debug messages. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 14:13:47.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 14:44:49.0 +0200 @@ -39,7 +39,7 @@ static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, Turn on/off debugging (default:off).); +MODULE_PARM_DESC(debug, \n\t\tDebugging level (0 to 2, default: 0 (off)).); static int no_poweroff; module_param(no_poweroff, int, 0644); @@ -239,6 +239,7 @@ static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val); static int xc4000_TunerReset(struct dvb_frontend *fe); +static void xc_debug_dump(struct xc4000_priv *priv); static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) { @@ -515,6 +516,15 @@ found = 1; } + /* Wait for stats to stabilize. + * Frame Lines needs two frame times after initial lock + * before it is valid. + */ + xc_wait(debug ? 100 : 10); + + if (debug) + xc_debug_dump(priv); + return found; } @@ -1085,12 +1095,6 @@ u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; - /* Wait for stats to stabilize. - * Frame Lines needs two frame times after initial lock - * before it is valid. - */ - xc_wait(100); - xc_get_ADC_Envelope(priv, adc_envelope); dprintk(1, *** ADC envelope (0-1023) = %d\n, adc_envelope); @@ -1103,16 +1107,18 @@ xc_get_version(priv, hw_majorversion, hw_minorversion, fw_majorversion, fw_minorversion); - dprintk(1, *** HW: V%02x.%02x, FW: V%02x.%02x\n, hw_majorversion, hw_minorversion, fw_majorversion, fw_minorversion); - xc_get_hsync_freq(priv, hsync_freq_hz); - dprintk(1, *** Horizontal sync frequency = %d Hz\n, hsync_freq_hz); + if (priv-video_standard XC4000_DTV6) { + xc_get_hsync_freq(priv, hsync_freq_hz); + dprintk(1, *** Horizontal sync frequency = %d Hz\n, + hsync_freq_hz); - xc_get_frame_lines(priv, frame_lines); - dprintk(1, *** Frame lines = %d\n, frame_lines); + xc_get_frame_lines(priv, frame_lines); + dprintk(1, *** Frame lines = %d\n, frame_lines); + } xc_get_quality(priv, quality); dprintk(1, *** Quality (0:8dB, 7:56dB) = %d\n, quality); @@ -1223,9 +1229,6 @@ } xc_tune_channel(priv, priv-freq_hz, XC_TUNE_DIGITAL); - if (debug) - xc_debug_dump(priv); - ret = 0; fail: @@ -1320,9 +1323,6 @@ xc_tune_channel(priv, priv-freq_hz, XC_TUNE_ANALOG); - if (debug) - xc_debug_dump(priv); - ret = 0; fail: @@ -1334,8 +1334,26 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) { struct xc4000_priv *priv = fe-tuner_priv; - dprintk(1, %s()\n, __func__); + *freq = priv-freq_hz; + + if (debug) { + mutex_lock(priv-lock); + if ((priv-cur_fw.type + (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) { + u16 snr = 0; + if (xc4000_readreg(priv, XREG_SNR, snr) == 0) { +mutex_unlock(priv-lock); +dprintk(1, %s() freq = %u, SNR = %d\n, + __func__, *freq, snr); +return 0; + } + } + mutex_unlock(priv-lock); + } + + dprintk(1, %s()\n, __func__); + return 0; } @@ -1355,13 +1373,17 @@ mutex_lock(priv-lock); - xc_get_lock_status(priv, lock_status); + if (priv-cur_fw.type BASE) + xc_get_lock_status(priv, lock_status); - mutex_unlock(priv-lock); + *status = (lock_status == 1 ? + TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0); + if (priv-cur_fw.type (DTV6 | DTV7 | DTV78 | DTV8)) + *status = (~TUNER_STATUS_STEREO); - dprintk(1, %s() lock_status = 0x%08x\n, __func__, lock_status); + mutex_unlock(priv-lock); - *status = lock_status; + dprintk(2, %s() lock_status = %d\n, __func__, lock_status); return 0; }
XC4000: setting registers
This patch implements setting the registers in xc4000_set_params() and xc4000_set_analog_params(). A new register is defined which enables filtering of the composite video output (this is needed to avoid bad picture quality with some boards). Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 14:46:15.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 15:22:06.0 +0200 @@ -131,6 +131,7 @@ #define XREG_SEEK_MODE0x06 #define XREG_POWER_DOWN 0x08 #define XREG_SIGNALSOURCE 0x0A +#define XREG_SMOOTHEDCVBS 0x0E #define XREG_AMPLITUDE0x10 /* Registers (Read-only) */ @@ -1218,15 +1219,35 @@ xc4000: xc_SetSignalSource(%d) failed\n, priv-rf_mode); goto fail; + } else { + u16 video_mode, audio_mode; + video_mode = XC4000_Standard[priv-video_standard].VideoMode; + audio_mode = XC4000_Standard[priv-video_standard].AudioMode; + if (type == DTV6 priv-firm_version != 0x0102) + video_mode |= 0x0001; + ret = xc_SetTVStandard(priv, video_mode, audio_mode); + if (ret != XC_RESULT_SUCCESS) { + printk(KERN_ERR xc4000: xc_SetTVStandard failed\n); + /* DJH - do not return when it fails... */ + /* goto fail; */ + } } - ret = xc_SetTVStandard(priv, - XC4000_Standard[priv-video_standard].VideoMode, - XC4000_Standard[priv-video_standard].AudioMode); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR xc4000: xc_SetTVStandard failed\n); - goto fail; + if (priv-card_type == XC4000_CARD_WINFAST_CX88) { + if (xc_write_reg(priv, XREG_D_CODE, 0) == 0) + ret = 0; + if (xc_write_reg(priv, XREG_AMPLITUDE, + (priv-firm_version == 0x0102 ? 132 : 134)) + != 0) + ret = -EREMOTEIO; + if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0) + ret = -EREMOTEIO; + if (ret != 0) { + printk(KERN_ERR xc4000: setting registers failed\n); + /* goto fail; */ + } } + xc_tune_channel(priv, priv-freq_hz, XC_TUNE_DIGITAL); ret = 0; @@ -1311,14 +1332,36 @@ xc4000: xc_SetSignalSource(%d) failed\n, priv-rf_mode); goto fail; + } else { + u16 video_mode, audio_mode; + video_mode = XC4000_Standard[priv-video_standard].VideoMode; + audio_mode = XC4000_Standard[priv-video_standard].AudioMode; + if (priv-video_standard XC4000_BG_PAL_A2) { + if (type NOGD) +video_mode = 0xFF7F; + } else if (priv-video_standard XC4000_I_PAL_NICAM) { + if (priv-card_type == XC4000_CARD_WINFAST_CX88 + priv-firm_version == 0x0102) +video_mode = 0xFEFF; + } + ret = xc_SetTVStandard(priv, video_mode, audio_mode); + if (ret != XC_RESULT_SUCCESS) { + printk(KERN_ERR xc4000: xc_SetTVStandard failed\n); + goto fail; + } } - ret = xc_SetTVStandard(priv, - XC4000_Standard[priv-video_standard].VideoMode, - XC4000_Standard[priv-video_standard].AudioMode); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR xc4000: xc_SetTVStandard failed\n); - goto fail; + if (priv-card_type == XC4000_CARD_WINFAST_CX88) { + if (xc_write_reg(priv, XREG_D_CODE, 0) == 0) + ret = 0; + if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0) + ret = -EREMOTEIO; + if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0) + ret = -EREMOTEIO; + if (ret != 0) { + printk(KERN_ERR xc4000: setting registers failed\n); + goto fail; + } } xc_tune_channel(priv, priv-freq_hz, XC_TUNE_ANALOG);
XC4000: added audio_std module parameter
The 'audio_std' module parameter makes it possible to fine tune some audio related aspects of the driver, like setting the exact audio standard (NICAM, A2, etc.) to be used for some video standards. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 15:23:35.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 15:38:30.0 +0200 @@ -49,6 +49,27 @@ \t\t2: powers device off when not used.\n \t\t0 (default): use device-specific default mode.); +#define XC4000_AUDIO_STD_B 1 +#define XC4000_AUDIO_STD_A2 2 +#define XC4000_AUDIO_STD_K3 4 +#define XC4000_AUDIO_STD_L 8 +#define XC4000_AUDIO_STD_INPUT1 16 +#define XC4000_AUDIO_STD_MONO 32 + +static int audio_std; +module_param(audio_std, int, 0644); +MODULE_PARM_DESC(audio_std, \n\t\tAudio standard. XC4000 audio decoder + explicitly needs to know\n + \t\twhat audio standard is needed for some video standards with\n + \t\taudio A2 or NICAM.\n + \t\tThe valid settings are a sum of:\n + \t\t 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n + \t\t 2: use A2 instead of NICAM or BTSC\n + \t\t 4: use SECAM/K3 instead of K1\n + \t\t 8: use PAL-D/K audio for SECAM-D/K\n + \t\t16: use FM radio input 1 instead of input 2\n + \t\t32: use mono audio (the lower three bits are ignored)); + #define XC4000_DEFAULT_FIRMWARE xc4000.fw static char firmware_name[30]; @@ -1343,6 +1364,8 @@ if (priv-card_type == XC4000_CARD_WINFAST_CX88 priv-firm_version == 0x0102) video_mode = 0xFEFF; + if (audio_std XC4000_AUDIO_STD_B) +video_mode |= 0x0080; } ret = xc_SetTVStandard(priv, video_mode, audio_mode); if (ret != XC_RESULT_SUCCESS) {
XC4000: implemented analog TV and radio
The following patch implements support for analog TV and FM radio. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 15:40:26.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 16:19:36.0 +0200 @@ -1283,69 +1283,150 @@ struct analog_parameters *params) { struct xc4000_priv *priv = fe-tuner_priv; + unsigned int type = 0; int ret = -EREMOTEIO; + if (params-mode == V4L2_TUNER_RADIO) { + dprintk(1, %s() frequency=%d (in units of 62.5Hz)\n, + __func__, params-frequency); + + mutex_lock(priv-lock); + + params-std = 0; + priv-freq_hz = params-frequency * 125L / 2; + + if (audio_std XC4000_AUDIO_STD_INPUT1) { + priv-video_standard = XC4000_FM_Radio_INPUT1; + type = FM | INPUT1; + } else { + priv-video_standard = XC4000_FM_Radio_INPUT2; + type = FM | INPUT2; + } + + goto tune_channel; + } + dprintk(1, %s() frequency=%d (in units of 62.5khz)\n, __func__, params-frequency); mutex_lock(priv-lock); - /* Fix me: it could be air. */ - priv-rf_mode = params-mode; - if (params-mode XC_RF_MODE_CABLE) - priv-rf_mode = XC_RF_MODE_CABLE; - /* params-frequency is in units of 62.5khz */ priv-freq_hz = params-frequency * 62500; - /* FIX ME: Some video standards may have several possible audio - standards. We simply default to one of them here. - */ + params-std = V4L2_STD_ALL; + /* if std is not defined, choose one */ + if (!params-std) + params-std = V4L2_STD_PAL_BG; + + if (audio_std XC4000_AUDIO_STD_MONO) + type = MONO; + if (params-std V4L2_STD_MN) { - /* default to BTSC audio standard */ - priv-video_standard = XC4000_MN_NTSC_PAL_BTSC; + params-std = V4L2_STD_MN; + if (audio_std XC4000_AUDIO_STD_MONO) { + priv-video_standard = XC4000_MN_NTSC_PAL_Mono; + } else if (audio_std XC4000_AUDIO_STD_A2) { + params-std |= V4L2_STD_A2; + priv-video_standard = XC4000_MN_NTSC_PAL_A2; + } else { + params-std |= V4L2_STD_BTSC; + priv-video_standard = XC4000_MN_NTSC_PAL_BTSC; + } goto tune_channel; } if (params-std V4L2_STD_PAL_BG) { - /* default to NICAM audio standard */ - priv-video_standard = XC4000_BG_PAL_NICAM; + params-std = V4L2_STD_PAL_BG; + if (audio_std XC4000_AUDIO_STD_MONO) { + priv-video_standard = XC4000_BG_PAL_MONO; + } else if (!(audio_std XC4000_AUDIO_STD_A2)) { + if (!(audio_std XC4000_AUDIO_STD_B)) { +params-std |= V4L2_STD_NICAM_A; +priv-video_standard = XC4000_BG_PAL_NICAM; + } else { +params-std |= V4L2_STD_NICAM_B; +priv-video_standard = XC4000_BG_PAL_NICAM; + } + } else { + if (!(audio_std XC4000_AUDIO_STD_B)) { +params-std |= V4L2_STD_A2_A; +priv-video_standard = XC4000_BG_PAL_A2; + } else { +params-std |= V4L2_STD_A2_B; +priv-video_standard = XC4000_BG_PAL_A2; + } + } goto tune_channel; } if (params-std V4L2_STD_PAL_I) { /* default to NICAM audio standard */ - priv-video_standard = XC4000_I_PAL_NICAM; + params-std = V4L2_STD_PAL_I | V4L2_STD_NICAM; + if (audio_std XC4000_AUDIO_STD_MONO) { + priv-video_standard = XC4000_I_PAL_NICAM_MONO; + } else { + priv-video_standard = XC4000_I_PAL_NICAM; + } goto tune_channel; } if (params-std V4L2_STD_PAL_DK) { - /* default to NICAM audio standard */ - priv-video_standard = XC4000_DK_PAL_NICAM; + params-std = V4L2_STD_PAL_DK; + if (audio_std XC4000_AUDIO_STD_MONO) { + priv-video_standard = XC4000_DK_PAL_MONO; + } else if (audio_std XC4000_AUDIO_STD_A2) { + params-std |= V4L2_STD_A2; + priv-video_standard = XC4000_DK_PAL_A2; + } else { + params-std |= V4L2_STD_NICAM; + priv-video_standard = XC4000_DK_PAL_NICAM; + } goto tune_channel; } if (params-std V4L2_STD_SECAM_DK) { - /* default to A2 DK1 audio standard */ - priv-video_standard = XC4000_DK_SECAM_A2DK1; + /* default to A2 audio standard */ + params-std = V4L2_STD_SECAM_DK | V4L2_STD_A2; + if (audio_std XC4000_AUDIO_STD_L) { + type = 0; + priv-video_standard = XC4000_DK_SECAM_NICAM; + } else if (audio_std XC4000_AUDIO_STD_MONO) { + priv-video_standard = XC4000_DK_SECAM_A2MONO; + } else if (audio_std XC4000_AUDIO_STD_K3) { + params-std |= V4L2_STD_SECAM_K3; + priv-video_standard = XC4000_DK_SECAM_A2LDK3; + } else { + priv-video_standard = XC4000_DK_SECAM_A2DK1; + } goto tune_channel; } if (params-std V4L2_STD_SECAM_L) { + /* default to NICAM audio standard */ + type = 0; + params-std = V4L2_STD_SECAM_L | V4L2_STD_NICAM; priv-video_standard = XC4000_L_SECAM_NICAM; goto tune_channel; } if (params-std V4L2_STD_SECAM_LC) { + /* default to NICAM audio standard */ + type = 0; + params-std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM; priv-video_standard = XC4000_LC_SECAM_NICAM; goto tune_channel; } tune_channel: + /* Fix me: it could be air. */ + priv-rf_mode = XC_RF_MODE_CABLE
XC4000: xc_tune_channel() cleanup
Minor coding changes related to the xc_tune_channel() function. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 16:22:18.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 16:29:34.0 +0200 @@ -516,12 +516,10 @@ return lockState; } -#define XC_TUNE_ANALOG 0 -#define XC_TUNE_DIGITAL 1 -static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode) +static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz) { - int found = 0; - int result = 0; + int found = 1; + int result; dprintk(1, %s(%u)\n, __func__, freq_hz); @@ -533,9 +531,10 @@ if (result != XC_RESULT_SUCCESS) return 0; - if (mode == XC_TUNE_ANALOG) { - if (WaitForLock(priv) == 1) - found = 1; + /* wait for lock only in analog TV mode */ + if ((priv-cur_fw.type (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) { + if (WaitForLock(priv) != 1) + found = 0; } /* Wait for stats to stabilize. @@ -1269,7 +1268,7 @@ } } - xc_tune_channel(priv, priv-freq_hz, XC_TUNE_DIGITAL); + xc_tune_channel(priv, priv-freq_hz); ret = 0; @@ -1468,7 +1467,7 @@ } } - xc_tune_channel(priv, priv-freq_hz, XC_TUNE_ANALOG); + xc_tune_channel(priv, priv-freq_hz); ret = 0;
XC4000: removed redundant tuner reset
This patch causes the tuner reset command to be ignored in the firmware code, since this only happens when the BASE/INIT1 firmware is loaded by check_firmware(), and in that case check_firmware() already calls the reset callback before starting to load the firmware. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 16:30:28.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 16:35:17.0 +0200 @@ -338,10 +338,12 @@ len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; if (len == 0x) { /* RESET command */ - result = xc4000_TunerReset(fe); index += 2; +#if 0 /* not needed, as already called by check_firmware() */ + result = xc4000_TunerReset(fe); if (result != XC_RESULT_SUCCESS) return result; +#endif } else if (len 0x8000) { /* WAIT command */ xc_wait(len 0x7FFF);
XC4000: detect XC4100
Added code to detect the XC4100 chip, which is presumably an analog-only value version of the XC4000. It is not sure, however, if any devices using this have actually been produced and sold, so the patch may be unneeded. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-04 16:35:50.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-04 16:40:09.0 +0200 @@ -140,7 +140,8 @@ /* Product id */ #define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000 -#define XC_PRODUCT_ID_FW_LOADED 0x0FA0 +#define XC_PRODUCT_ID_XC4000 0x0FA0 +#define XC_PRODUCT_ID_XC4100 0x1004 /* Registers (Write-only) */ #define XREG_INIT 0x00 @@ -1071,7 +1072,9 @@ #endif /* Check that the tuner hardware model remains consistent over time. */ - if (priv-hwmodel == 0 hwmodel == 4000) { + if (priv-hwmodel == 0 + (hwmodel == XC_PRODUCT_ID_XC4000 || + hwmodel == XC_PRODUCT_ID_XC4100)) { priv-hwmodel = hwmodel; priv-hwvers = version 0xff00; } else if (priv-hwmodel == 0 || priv-hwmodel != hwmodel || @@ -1678,7 +1681,8 @@ } switch (id) { - case XC_PRODUCT_ID_FW_LOADED: + case XC_PRODUCT_ID_XC4000: + case XC_PRODUCT_ID_XC4100: printk(KERN_INFO xc4000: Successfully identified at address 0x%02x\n, cfg-i2c_address);
Re: XC4000: added card_type
On 06/03/2011 04:00 PM, Mauro Carvalho Chehab wrote: While the xc4000 is not merged upstream, we may have such hack, but before merging, this issue should be solved. However, it seems better to just do the right thing since the beginning: just add a patch for cx88 adding the xc4000 boards there and filling the config stuff inside cx88 driver. I do intend to remove the card_type code later, and only send cx88 patches once the interface is cleaned up. It is only included for now to have a working code without conflicting patches, and I do not know exactly what the config structure should eventually contain, that is, some of the current board-specific 'if' statements may actually turn out to be unnecessary and can be made the same for all cards. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
XC4000: updated standards table
This patch makes the following changes to the standards table: - added 'u16 int_freq' to struct XC_TV_STANDARD (needed for analog TV and radio, 0 for DVB-T) - added new standard for SECAM-D/K video with PAL-D/K audio - the 'int_freq' values are now specified in the table - changed VideoMode for NTSC and PAL-B/G standards Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-03 14:33:40.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-03 15:41:55.0 +0200 @@ -94,7 +94,7 @@ }; /* Misc Defines */ -#define MAX_TV_STANDARD 23 +#define MAX_TV_STANDARD 24 #define XC_MAX_I2C_WRITE_LENGTH 64 /* Signal Types */ @@ -172,6 +172,7 @@ const char *Name; u16 AudioMode; u16 VideoMode; + u16 int_freq; }; /* Tuner standards */ @@ -190,39 +191,41 @@ #define XC4000_DK_SECAM_A2DK1 12 #define XC4000_DK_SECAM_A2LDK3 13 #define XC4000_DK_SECAM_A2MONO 14 -#define XC4000_L_SECAM_NICAM 15 -#define XC4000_LC_SECAM_NICAM 16 -#define XC4000_DTV6 17 -#define XC4000_DTV8 18 -#define XC4000_DTV7_8 19 -#define XC4000_DTV7 20 -#define XC4000_FM_Radio_INPUT2 21 -#define XC4000_FM_Radio_INPUT1 22 +#define XC4000_DK_SECAM_NICAM 15 +#define XC4000_L_SECAM_NICAM 16 +#define XC4000_LC_SECAM_NICAM 17 +#define XC4000_DTV6 18 +#define XC4000_DTV8 19 +#define XC4000_DTV7_8 20 +#define XC4000_DTV7 21 +#define XC4000_FM_Radio_INPUT2 22 +#define XC4000_FM_Radio_INPUT1 23 static struct XC_TV_STANDARD XC4000_Standard[MAX_TV_STANDARD] = { - {M/N-NTSC/PAL-BTSC, 0x, 0x8020}, - {M/N-NTSC/PAL-A2, 0x, 0x8020}, - {M/N-NTSC/PAL-EIAJ, 0x0040, 0x8020}, - {M/N-NTSC/PAL-Mono, 0x0078, 0x8020}, - {B/G-PAL-A2,0x, 0x8059}, - {B/G-PAL-NICAM, 0x0004, 0x8059}, - {B/G-PAL-MONO, 0x0078, 0x8059}, - {I-PAL-NICAM, 0x0080, 0x8049}, - {I-PAL-NICAM-MONO, 0x0078, 0x8049}, - {D/K-PAL-A2,0x, 0x8049}, - {D/K-PAL-NICAM, 0x0080, 0x8049}, - {D/K-PAL-MONO, 0x0078, 0x8049}, - {D/K-SECAM-A2 DK1, 0x, 0x8049}, - {D/K-SECAM-A2 L/DK3, 0x, 0x8049}, - {D/K-SECAM-A2 MONO, 0x0078, 0x8049}, - {L-SECAM-NICAM, 0x8080, 0x0009}, - {L'-SECAM-NICAM,0x8080, 0x4009}, - {DTV6, 0x00C0, 0x8002}, - {DTV8, 0x00C0, 0x800B}, - {DTV7/8,0x00C0, 0x801B}, - {DTV7, 0x00C0, 0x8007}, - {FM Radio-INPUT2, 0x0008, 0x9800}, - {FM Radio-INPUT1, 0x0008, 0x9000} + {M/N-NTSC/PAL-BTSC, 0x, 0x80A0, 4500}, + {M/N-NTSC/PAL-A2, 0x, 0x80A0, 4600}, + {M/N-NTSC/PAL-EIAJ, 0x0040, 0x80A0, 4500}, + {M/N-NTSC/PAL-Mono, 0x0078, 0x80A0, 4500}, + {B/G-PAL-A2, 0x, 0x8159, 5640}, + {B/G-PAL-NICAM, 0x0004, 0x8159, 5740}, + {B/G-PAL-MONO, 0x0078, 0x8159, 5500}, + {I-PAL-NICAM, 0x0080, 0x8049, 6240}, + {I-PAL-NICAM-MONO, 0x0078, 0x8049, 6000}, + {D/K-PAL-A2, 0x, 0x8049, 6380}, + {D/K-PAL-NICAM, 0x0080, 0x8049, 6200}, + {D/K-PAL-MONO, 0x0078, 0x8049, 6500}, + {D/K-SECAM-A2 DK1, 0x, 0x8049, 6340}, + {D/K-SECAM-A2 L/DK3, 0x, 0x8049, 6000}, + {D/K-SECAM-A2 MONO, 0x0078, 0x8049, 6500}, + {D/K-SECAM-NICAM, 0x0080, 0x8049, 6200}, + {L-SECAM-NICAM, 0x8080, 0x0009, 6200}, + {L'-SECAM-NICAM, 0x8080, 0x4009, 6200}, + {DTV6, 0x00C0, 0x8002,0}, + {DTV8, 0x00C0, 0x800B,0}, + {DTV7/8, 0x00C0, 0x801B,0}, + {DTV7, 0x00C0, 0x8007,0}, + {FM Radio-INPUT2, 0x0008, 0x9800,10700}, + {FM Radio-INPUT1, 0x0008, 0x9000,10700} }; static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
XC4000: added support for 7 MHz DVB-T
The following patch implements support for DVB-T with 7 MHz bandwidth. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-03 15:47:04.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-03 16:34:25.0 +0200 @@ -1183,15 +1183,28 @@ type = DTV6; break; case BANDWIDTH_7_MHZ: - printk(KERN_ERR xc4000 bandwidth 7MHz not supported\n); + priv-bandwidth = BANDWIDTH_7_MHZ; + priv-video_standard = XC4000_DTV7; + priv-freq_hz = params-frequency - 225; type = DTV7; - return -EINVAL; + break; case BANDWIDTH_8_MHZ: priv-bandwidth = BANDWIDTH_8_MHZ; priv-video_standard = XC4000_DTV8; priv-freq_hz = params-frequency - 275; type = DTV8; break; + case BANDWIDTH_AUTO: + if (params-frequency 4) { +priv-bandwidth = BANDWIDTH_7_MHZ; +priv-freq_hz = params-frequency - 225; + } else { +priv-bandwidth = BANDWIDTH_8_MHZ; +priv-freq_hz = params-frequency - 275; + } + priv-video_standard = XC4000_DTV7_8; + type = DTV78; + break; default: printk(KERN_ERR xc4000 bandwidth not set!\n); return -EINVAL;
XC4000: added mutex
This patch adds a mutex to xc4000_priv, to protect the driver from being accessed by multiple processes at the same time. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-03 16:35:23.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-03 17:02:59.0 +0200 @@ -28,6 +28,7 @@ #include linux/delay.h #include linux/dvb/frontend.h #include linux/i2c.h +#include linux/mutex.h #include asm/unaligned.h #include dvb_frontend.h @@ -91,6 +92,7 @@ struct firmware_properties cur_fw; __u16 hwmodel; __u16 hwvers; + struct mutex lock; }; /* Misc Defines */ @@ -1144,10 +1146,12 @@ { struct xc4000_priv *priv = fe-tuner_priv; unsigned int type; - int ret; + int ret = -EREMOTEIO; dprintk(1, %s() frequency=%d (Hz)\n, __func__, params-frequency); + mutex_lock(priv-lock); + if (fe-ops.info.type == FE_ATSC) { dprintk(1, %s() ATSC\n, __func__); switch (params-u.vsb.modulation) { @@ -1171,7 +1175,8 @@ type = DTV6; break; default: - return -EINVAL; + ret = -EINVAL; + goto fail; } } else if (fe-ops.info.type == FE_OFDM) { dprintk(1, %s() OFDM\n, __func__); @@ -1207,28 +1212,29 @@ break; default: printk(KERN_ERR xc4000 bandwidth not set!\n); - return -EINVAL; + ret = -EINVAL; + goto fail; } priv-rf_mode = XC_RF_MODE_AIR; } else { printk(KERN_ERR xc4000 modulation type not supported!\n); - return -EINVAL; + ret = -EINVAL; + goto fail; } dprintk(1, %s() frequency=%d (compensated)\n, __func__, priv-freq_hz); /* Make sure the correct firmware type is loaded */ - if (check_firmware(fe, type, 0, priv-if_khz) != XC_RESULT_SUCCESS) { - return -EREMOTEIO; - } + if (check_firmware(fe, type, 0, priv-if_khz) != XC_RESULT_SUCCESS) + goto fail; ret = xc_SetSignalSource(priv, priv-rf_mode); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR - xc4000: xc_SetSignalSource(%d) failed\n, - priv-rf_mode); - return -EREMOTEIO; + xc4000: xc_SetSignalSource(%d) failed\n, + priv-rf_mode); + goto fail; } ret = xc_SetTVStandard(priv, @@ -1236,33 +1242,32 @@ XC4000_Standard[priv-video_standard].AudioMode); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR xc4000: xc_SetTVStandard failed\n); - return -EREMOTEIO; - } -#ifdef DJH_DEBUG - ret = xc_set_IF_frequency(priv, priv-if_khz); - if (ret != XC_RESULT_SUCCESS) { - printk(KERN_ERR xc4000: xc_Set_IF_frequency(%d) failed\n, - priv-if_khz); - return -EIO; + goto fail; } -#endif xc_tune_channel(priv, priv-freq_hz, XC_TUNE_DIGITAL); if (debug) xc_debug_dump(priv); - return 0; + ret = 0; + +fail: + mutex_unlock(priv-lock); + + return ret; } static int xc4000_set_analog_params(struct dvb_frontend *fe, struct analog_parameters *params) { struct xc4000_priv *priv = fe-tuner_priv; - int ret; + int ret = -EREMOTEIO; dprintk(1, %s() frequency=%d (in units of 62.5khz)\n, __func__, params-frequency); + mutex_lock(priv-lock); + /* Fix me: it could be air. */ priv-rf_mode = params-mode; if (params-mode XC_RF_MODE_CABLE) @@ -1317,16 +1322,15 @@ tune_channel: /* FIXME - firmware type not being set properly */ - if (check_firmware(fe, DTV8, 0, priv-if_khz) != XC_RESULT_SUCCESS) { - return -EREMOTEIO; - } + if (check_firmware(fe, DTV8, 0, priv-if_khz) != XC_RESULT_SUCCESS) + goto fail; ret = xc_SetSignalSource(priv, priv-rf_mode); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR - xc4000: xc_SetSignalSource(%d) failed\n, - priv-rf_mode); - return -EREMOTEIO; + xc4000: xc_SetSignalSource(%d) failed\n, + priv-rf_mode); + goto fail; } ret = xc_SetTVStandard(priv, @@ -1334,7 +1338,7 @@ XC4000_Standard[priv-video_standard].AudioMode); if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR xc4000: xc_SetTVStandard failed\n); - return -EREMOTEIO; + goto fail; } xc_tune_channel(priv, priv-freq_hz, XC_TUNE_ANALOG); @@ -1342,7 +1346,12 @@ if (debug) xc_debug_dump(priv); - return 0; + ret = 0; + +fail: + mutex_unlock(priv-lock); + + return ret; } static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) @@ -1367,8 +1376,12 @@ struct xc4000_priv *priv = fe-tuner_priv; u16 lock_status = 0; + mutex_lock(priv-lock); + xc_get_lock_status(priv, lock_status); + mutex_unlock(priv-lock); + dprintk(1, %s() lock_status = 0x%08x\n, __func__, lock_status); *status = lock_status; @@ -1385,9 +1398,13 @@ static int xc4000_init(struct dvb_frontend *fe) { struct xc4000_priv *priv = fe-tuner_priv; + int ret; dprintk(1, %s()\n, __func__); - if (check_firmware(fe, DTV8, 0, priv-if_khz) != XC_RESULT_SUCCESS) { + mutex_lock(priv-lock); + ret = check_firmware(fe, DTV8, 0, priv-if_khz); + mutex_unlock(priv-lock); + if (ret != XC_RESULT_SUCCESS) { printk(KERN_ERR xc4000: Unable
XC4000: fixed frequency error
The xc_get_frequency_error() function reported the frequency error incorrectly. The data read from the hardware is a signed integer, in 15625 Hz units. The attached patch fixes the bug. Signed-off-by: Istvan Varga istva...@mailbox.hu diff -uNr xc4000_orig/drivers/media/common/tuners/xc4000.c xc4000/drivers/media/common/tuners/xc4000.c --- xc4000_orig/drivers/media/common/tuners/xc4000.c 2011-06-03 17:09:54.0 +0200 +++ xc4000/drivers/media/common/tuners/xc4000.c 2011-06-03 17:14:12.0 +0200 @@ -418,8 +418,9 @@ if (result != XC_RESULT_SUCCESS) return result; - tmp = (u32)regData; - (*freq_error_hz) = (tmp * 15625) / 1000; + tmp = (u32)regData 0xU; + tmp = (tmp 0x8000U ? tmp : 0x1U - tmp); + (*freq_error_hz) = tmp * 15625; return result; }
Re: [PATCH] cx88: implement sharpness control
On 04/09/2010 06:33 AM, Mauro Carvalho Chehab wrote: You're not adjusting the sharpness. Instead, you're changing the vertical tap filter, and just for the even frames, plus the notch filter. Tricky, and you're probably affecting the sharpness, but on an indirect and non-linear way, as you're adjusting different measures. No, I actually change the luma peak filter, which can add a peak of up to about 6 dB centered at the chroma subcarrier frequency. So, it does increase sharpness, and horizontally, not vertically. I did test the patch before submitting it. Also, there is code in the patch that sets the parameter for the odd field as well. So, in fact, this control affects three registers: two for the peak filter, and a third one for the notch filter. If this is really needed, it would be better to break it into two controls (one for the notch filter and another for the vertical tap filter). Yes, that could possibly have been a good idea to have a separate control for the notch filter. It was just easier to implement this way, and I think there is no existing control that would be well suited for the notch filter. Since both parameters do affect sharpness in some way, I implemented it as a single control, rather than creating a separate new one. Also, the side effect is not good: if you're using those bits, your code should assure that no other part of the driver will touch on the used bits, and that the device will be initialized with the default standard. That is correct, and I did note that it would be addressed later if the general idea of implementing the control is accepted. Fortunately, the registers are changed elsewhere at only about two places. By the way, did you have a look at the other two cx88 patches (containing minor fixes only) I sent at the same time ? -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] cx88: implement sharpness control
This patch adds support for V4L2_CID_SHARPNESS by changing the luma peak filter and notch filter. It can be set in the range 0 to 9, with 0 being the original and default mode. One minor problem is that other code that sets the registers being used (for example when switching TV channels) could reset the control to the default. This could be avoided by making changes so that the bits used to implement this control are not overwritten. Signed-off-by: Istvan Varga istv...@users.sourceforge.net diff -r -d -N -U4 v4l-dvb-a79dd2ae4d0e.old/linux/drivers/media/video/cx88/cx88-video.c v4l-dvb-a79dd2ae4d0e/linux/drivers/media/video/cx88/cx88-video.c --- v4l-dvb-a79dd2ae4d0e.old/linux/drivers/media/video/cx88/cx88-video.c 2010-03-23 03:39:52.0 +0100 +++ v4l-dvb-a79dd2ae4d0e/linux/drivers/media/video/cx88/cx88-video.c 2010-03-23 19:07:26.0 +0100 @@ -220,9 +220,24 @@ .off = 0, .reg = MO_UV_SATURATION, .mask = 0x00ff, .shift = 0, - },{ + }, { + .v = { + .id= V4L2_CID_SHARPNESS, + .name = Sharpness, + .minimum = 0, + .maximum = 9, + .default_value = 0x0, + .type = V4L2_CTRL_TYPE_INTEGER, + }, + .off = 0, + /* NOTE: the value is converted and written to both even + and odd registers in the code */ + .reg = MO_FILTER_ODD, + .mask = 7 7, + .shift = 7, + }, { .v = { .id= V4L2_CID_CHROMA_AGC, .name = Chroma AGC, .minimum = 0, @@ -300,8 +315,9 @@ V4L2_CID_HUE, V4L2_CID_AUDIO_VOLUME, V4L2_CID_AUDIO_BALANCE, V4L2_CID_AUDIO_MUTE, + V4L2_CID_SHARPNESS, V4L2_CID_CHROMA_AGC, V4L2_CID_COLOR_KILLER, 0 }; @@ -1187,8 +1203,13 @@ break; case V4L2_CID_AUDIO_VOLUME: ctl-value = 0x3f - (value 0x3f); break; + case V4L2_CID_SHARPNESS: + ctl-value = (value 0x0380) 6; + ctl-value = (ctl-value 8 ? 0 : (ctl-value - 6)) + | ((cx_read(MO_HTOTAL) 0x0800) 11); + break; default: ctl-value = ((value + (c-off c-shift)) c-mask) c-shift; break; } @@ -1246,8 +1267,16 @@ value=(value*0x5a)/0x7f8|value; } mask=0x; break; + case V4L2_CID_SHARPNESS: + /* use 4xFsc or square pixel notch filter */ + cx_andor(MO_HTOTAL, 0x1800, (ctl-value 1) 11); + /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ + value = (ctl-value 2 ? 0 : (((ctl-value + 6) 0x0E) 6)); + /* needs to be set for both fields */ + cx_andor(MO_FILTER_EVEN, mask, value); + break; case V4L2_CID_CHROMA_AGC: /* Do not allow chroma AGC to be enabled for SECAM */ value = ((ctl-value - c-off) c-shift) c-mask; if (core-tvnorm V4L2_STD_SECAM value)
[PATCH] cx88: fix setting input when using DVB
In cx88-mpeg.c, there is code that sets core-input to CX88_VMUX_DVB. However, this may be incorrect, since core-input is actually an index to core-board.input[], which has not enough elements to be indexed by the value of CX88_VMUX_DVB. So, the modified code searches core-board.input[] for an input with a type of CX88_VMUX_DVB, and if it does not find one, the index is simply set to zero. The change may not have much effect, though, since it appears the only case when core-input is actually used is when the current input is being queried. Signed-off-by: Istvan Varga istv...@users.sourceforge.net -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] cx88: fix setting input when using DVB
(Sorry for the double post, the previous one did not include the patch) In cx88-mpeg.c, there is code that sets core-input to CX88_VMUX_DVB. However, this may be incorrect, since core-input is actually an index to core-board.input[], which has not enough elements to be indexed by the value of CX88_VMUX_DVB. So, the modified code searches core-board.input[] for an input with a type of CX88_VMUX_DVB, and if it does not find one, the index is simply set to zero. The change may not have much effect, though, since it appears the only case when core-input is actually used is when the current input is being queried. Signed-off-by: Istvan Varga istv...@users.sourceforge.net diff -r -d -N -U4 v4l-dvb-a79dd2ae4d0e.old/linux/drivers/media/video/cx88/cx88-mpeg.c v4l-dvb-a79dd2ae4d0e/linux/drivers/media/video/cx88/cx88-mpeg.c --- v4l-dvb-a79dd2ae4d0e.old/linux/drivers/media/video/cx88/cx88-mpeg.c 2010-03-23 03:39:52.0 +0100 +++ v4l-dvb-a79dd2ae4d0e/linux/drivers/media/video/cx88/cx88-mpeg.c 2010-03-23 19:07:26.0 +0100 @@ -637,15 +637,24 @@ /* Driver asked for hardware access. */ static int cx8802_request_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv-core; + unsigned int i; /* Fail a request for hardware if the device is busy. */ if (core-active_type_id != CX88_BOARD_NONE core-active_type_id != drv-type_id) return -EBUSY; - core-input = CX88_VMUX_DVB; + core-input = 0; + for (i = 0; + i (sizeof(core-board.input) / sizeof(struct cx88_input)); + i++) { + if (core-board.input[i].type == CX88_VMUX_DVB) { + core-input = i; + break; + } + } if (drv-advise_acquire) { mutex_lock(drv-core-lock);
Re: [PATCH] DTV2000 H Plus issues
An updated patch that includes the PxDVR3200 H (107d:6f39) support is now available at http://istvanv.users.sourceforge.net/v4l/xc4000.html. On 03/22/2010 07:33 PM, istva...@mailbox.hu wrote: On 03/15/2010 05:15 AM, Devin Heitmueller wrote: I'll try to go through my tree and see if I can get something upstream this week which you could build on. Are there any news on this ? By the way, I have just received this mail from Mirek Slugen, with a patch for PxDVR3200 with XC4000 tuner. Should that patch also be submitted ? On 03/22/2010 04:40 PM, Mirek Slugeň wrote: First I would like to thank you for your work on XC4000 Leadtek tuners, analog TV, analog FM and DVB-T works great. I created patch for new revision of Leadtek DVR3200 (xc4000) based on your patch and it works also (patch is included). After long testing I found only one small bug, signal strength is not working on DVB-T XC4000 based tuners, so i will try to fix it. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] DTV2000 H Plus issues
On 03/15/2010 05:15 AM, Devin Heitmueller wrote: I'll try to go through my tree and see if I can get something upstream this week which you could build on. Are there any news on this ? By the way, I have just received this mail from Mirek Slugen, with a patch for PxDVR3200 with XC4000 tuner. Should that patch also be submitted ? On 03/22/2010 04:40 PM, Mirek Slugeň wrote: First I would like to thank you for your work on XC4000 Leadtek tuners, analog TV, analog FM and DVB-T works great. I created patch for new revision of Leadtek DVR3200 (xc4000) based on your patch and it works also (patch is included). After long testing I found only one small bug, signal strength is not working on DVB-T XC4000 based tuners, so i will try to fix it. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] DTV2000 H Plus issues
On 03/15/2010 05:15 AM, Devin Heitmueller wrote: I've done essentially no analysis into the tuning performance of the current driver - validating different frequency ranges and modulation types or bandwidths. I've done no testing of tuning lock time, minimal application validation Well, so far it definitely seems usable and not apparently worse than on Windows. If more developers can test and review it, then it is more likely that any issues can be found and fixed or improved. and no effort toward making sure the power management works. I did implement power management (by writing to register 8, and setting a flag that forces resetting the tuner and reloading all firmware data on the next use), although it is disabled by default for the cards that I added support for (it is apparently not used on Windows, either). I'll try to go through my tree and see if I can get something upstream this week which you could build on. I think adding xc4000.c/h and the few changes shown at the end of this post to incorporate XC4000 as a tuner type should be enough. Did you review the changes I made to the XC4000 driver ? Is there something that is unneeded or should be done differently ? Do you have a fixed firmware file, or are the ones I created usable ? Once that is done, you will need to break up your huge patch into a series of small incremental patches (with proper descriptions for the changes), since there is no way a single patch is going to be accepted upstream which has all of your changes. OK. Should I also create patches for any of the unrelated cx88 fixes/changes ? Also, you should *not* be submitting board profiles that are completely unvalidated. I saw your email on Feb 19th, where you dumped out a list of tuners that you think might *possibly* work. You should only submit board definitions for devices that either you have tested or you have gotten a user to test. It is far worse to have broken code in there (creating the illusion of a product being supported), then for there to be no support at all. When users complain about a particular board not working, you can work with them to get it supported. Of the additional boards, 107d:6f38 (WinFast DTV1800 H with XC4000 tuner instead of XC3028) has been reported by one user to work in analog mode, while DVB was untested. Is that enough to keep the board profile ? I have 107d:6f42 (DTV2000 H Plus), and tested it extensively in analog and FM radio mode; another user tested DVB-T, and reported it to work well (I have got no information about details like bandwidth used, though). As far as I know, the only difference between the above two cards that is relevant to drivers is that the latter has an additional GPIO for selecting the antenna/cable RF input. I have no problems with removing the various TV2000 XP Global revisions from the patches, as I do not even know if anyone actually has one of those cards. diff -r -d -N -U4 v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Kconfig v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Kconfig --- v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Kconfig 2010-03-10 03:00:59.0 +0100 +++ v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Kconfig 2010-03-10 17:12:02.0 +0100 @@ -22,8 +22,9 @@ default VIDEO_MEDIA I2C depends on VIDEO_MEDIA I2C select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE @@ -150,8 +151,17 @@ A driver for the silicon tuner XC5000 from Xceive. This device is only used inside a SiP called together with a demodulator for now. +config MEDIA_TUNER_XC4000 + tristate Xceive XC4000 silicon tuner + depends on VIDEO_MEDIA I2C + default m if MEDIA_TUNER_CUSTOMISE + help + A driver for the silicon tuner XC4000 from Xceive. + This device is only used inside a SiP called together with a + demodulator for now. + config MEDIA_TUNER_MXL5005S tristate MaxLinear MSL5005S silicon tuner depends on VIDEO_MEDIA I2C default m if MEDIA_TUNER_CUSTOMISE diff -r -d -N -U4 v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Makefile v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Makefile --- v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Makefile 2010-03-10 03:00:59.0 +0100 +++ v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Makefile 2010-03-10 17:12:02.0 +0100 @@ -15,8 +15,9 @@ obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
Re: [PATCH] DTV2000 H Plus issues
On 02/18/2010 01:11 AM, Devin Heitmueller wrote: Yeah, my plan at this point was to submit a PULL request once I felt the driver is stable For those particular cards that my patch adds support for, it seems to be stable, and I have been using it for months. Perhaps stability issues in xc4000.c are specific to the PCTV 340e and its dib0700 I2C problems ? -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] DTV2000 H Plus issues
I have finally received some feedback on DVB-T, and it reportedly works, although with a minor bug: it was necessary to use the cable connector instead of the antenna one. There is an updated patch at the web page http://www.sharemation.com/IstvanV/v4l/xc4000.html that attempts to correct this problem. It also includes a few CX88 changes that are not related to adding support for XC4000 based cards, and could possibly be released as separate patches: - implements a sharpness control using the CX2388x peaking filter and changing the notch filter - in two places (cx88-core.c and cx88-video.c) code that checked for CX88_VMUX_TELEVISION did not also check for CX88_VMUX_CABLE; this was the reason why selecting the audio standard did not work for the cable input - in cx88-mpeg.c, there was code that set core-input to CX88_VMUX_DVB; this does not seem to make sense, since core-input is an index to an array (core-board.input), while the CX88_VMUX_* values are not intended to be used as indexes, but rather values of the 'type' member of struct cx88_input. But it is also not obvious if this has any actual effect other than what is reported as the current input when queried by an application. In any case, I changed the code to search for an input of type CX88_VMUX_DVB, or set the input to 0 if it is not found -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] DTV2000 H Plus issues
Well, it is not really a problem, if it is not merged, so this updated version is only for those who want to test it: http://www.sharemation.com/IstvanV/v4l/xc4000-winfast-14021dfc00f3.patch - in xc4000.c, power management may default to on or off depending on the card type - autodetects and (hopefully) supports cards with the following PCI IDs, based on Windows INF files: 107D:6619 WinFast TV2000 XP Global (this is actually the same as 6618 and 6F18) 107D:6F36 WinFast TV2000 XP Global with XC4100 (analog-only XC4000 ?) tuner 107D:6F38 WinFast DTV1800 H with XC4000 tuner 107D:6F42 WinFast DTV2000 H Plus 107D:6F43 WinFast TV2000 XP Global with XC4100 tuner and different GPIOs Not all of these card versions may actually exist in practice, though, only 6F38 and 6F42 are confirmed so far. - added a new sharpness control to the CX88 driver On 02/18/2010 12:59 AM, Devin Heitmueller wrote: I would hate to come across as a jerk here, but he cannot provide his SOB for this patch, as I wrote about 95% of the code here. It's derived from a tree I have been working on for the PCTV 340e: -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: DTV2000 H Plus issues
Here is another patch, with a few minor changes. It depends on the previously posted patches, so those should be applied first. diff -r -d -N -U4 v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c --- v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c 2010-02-12 19:14:24.0 +0100 +++ v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c 2010-02-12 19:20:35.0 +0100 @@ -256,8 +256,9 @@ }; static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val); static int xc4000_TunerReset(struct dvb_frontend *fe); +static void xc_debug_dump(struct xc4000_priv *priv); static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) { struct i2c_msg msg = { .addr = priv-i2c_props.addr, @@ -332,12 +333,14 @@ (i2c_sequence[index + 1] != 0xFF)) { len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; if (len == 0x) { /* RESET command */ - result = xc4000_TunerReset(fe); index += 2; +#if 0 /* not needed, as already called by check_firmware() */ + result = xc4000_TunerReset(fe); if (result != XC_RESULT_SUCCESS) return result; +#endif } else if (len 0x8000) { /* WAIT command */ xc_wait(len 0x7FFF); index += 2; @@ -472,14 +475,8 @@ return 0; } -/* WAS THERE -static int xc_get_buildversion(struct xc4000_priv *priv, u16 *buildrev) -{ - return xc4000_readreg(priv, XREG_BUILD, buildrev); -}*/ - static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz) { u16 regData; int result; @@ -516,14 +513,12 @@ } return lockState; } -#define XC_TUNE_ANALOG 0 -#define XC_TUNE_DIGITAL 1 -static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode) +static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz) { - int found = 0; - int result = 0; + int found = 1; + int result; dprintk(1, %s(%u)\n, __func__, freq_hz); /* Don't complain when the request fails because of i2c stretching */ @@ -533,13 +528,23 @@ if (result != XC_RESULT_SUCCESS) return 0; - if (mode == XC_TUNE_ANALOG) { - if (WaitForLock(priv) == 1) - found = 1; + /* wait for lock only in analog TV mode */ + if ((priv-cur_fw.type (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) { + if (WaitForLock(priv) == 0) + found = 0; } + /* Wait for stats to stabilize. + * Frame Lines needs two frame times after initial lock + * before it is valid. + */ + xc_wait(debug ? 100 : 10); + + if (debug) + xc_debug_dump(priv); + return found; } static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val) @@ -1108,17 +1113,8 @@ u16 quality; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; - if (!(priv-cur_fw.type BASE)) - return; - - /* Wait for stats to stabilize. - * Frame Lines needs two frame times after initial lock - * before it is valid. - */ - xc_wait(100); - xc_get_ADC_Envelope(priv, adc_envelope); dprintk(1, *** ADC envelope (0-1023) = %d\n, adc_envelope); xc_get_frequency_error(priv, freq_error_hz); @@ -1269,12 +1265,10 @@ /* goto fail; */ } } - xc_tune_channel(priv, priv-freq_hz, XC_TUNE_DIGITAL); + xc_tune_channel(priv, priv-freq_hz); - if (debug) - xc_debug_dump(priv); ret = 0; fail: mutex_unlock(priv-lock); @@ -1470,12 +1464,10 @@ goto fail; } } - xc_tune_channel(priv, priv-freq_hz, XC_TUNE_ANALOG); + xc_tune_channel(priv, priv-freq_hz); - if (debug) - xc_debug_dump(priv); ret = 0; fail: mutex_unlock(priv-lock); @@ -1549,9 +1541,9 @@ mutex_lock(priv-lock); /* Avoid firmware reload on slow devices */ - if (!no_poweroff priv-cur_fw.type != XC_POWERED_DOWN) { + if (!no_poweroff (priv-cur_fw.type BASE) != 0) { /* force reset and firmware reload */ priv-cur_fw.type = XC_POWERED_DOWN; if (xc_write_reg(priv, XREG_POWER_DOWN, 0) @@ -1560,8 +1552,9 @@ xc4000: %s() unable to shutdown tuner\n, __func__); ret = -EREMOTEIO; } + xc_wait(20); } mutex_unlock(priv-lock); @@ -1638,9 +1631,10 @@ instance = hybrid_tuner_request_state(struct xc4000_priv, priv, hybrid_tuner_instance_list, i2c, cfg-i2c_address, xc4000); - priv-card_type = cfg-card_type; + if (cfg-card_type != XC4000_CARD_GENERIC) + priv-card_type = cfg-card_type; switch (instance) { case 0: goto fail; break; @@ -1703,12 +1697,21 @@ memcpy(fe-ops.tuner_ops, xc4000_tuner_ops, sizeof(struct dvb_tuner_ops)); + if (instance == 1) { + int ret; + mutex_lock(priv-lock); + ret = xc4000_fwupload(fe); + mutex_unlock(priv-lock); + if (ret != XC_RESULT_SUCCESS) + goto fail2; + } + return fe; fail: mutex_unlock(xc4000_list_mutex); - +fail2: xc4000_release(fe); return NULL; } EXPORT_SYMBOL(xc4000_attach); diff -r -d -N -U4 v4l-dvb-28f5eca12bb0.old/linux/drivers/media/video/tuner-core.c
Re: DTV2000 H Plus issues
A correction to the previous post: this line: if (WaitForLock(priv) == 0) should actually be: if (WaitForLock(priv) != 1) It does not have an effect on the operation of the driver, though, since the value set depending on this line is not used. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: DTV2000 H Plus issues
Update: the following patch, which should be applied after the previous ones, makes a few additional changes to the XC4000 driver: - adds support for DTV7 - implements power management - adds a mutex and locking for tuner operations - some unused or unneeded code has been removed On 02/09/2010 06:35 PM, istva...@mailbox.hu wrote: There are two separate patches for v4l-dvb revision 28f5eca12bb0: the first one adds the XC4000 driver, while the second one adds support for the Leadtek WinFast DTV2000H Plus card in the CX88 driver. http://www.sharemation.com/IstvanV/v4l/xc4000-28f5eca12bb0.patch http://www.sharemation.com/IstvanV/v4l/cx88-dtv2000h+-28f5eca12bb0.patch These new firmware files are more complete than the previous ones, but are not compatible with the original driver. Both version 1.2 and 1.4 are available: http://www.sharemation.com/IstvanV/v4l/xc4000-1.2.fw http://www.sharemation.com/IstvanV/v4l/xc4000-1.4.fw The following simple utility was used for creating the firmware files. http://www.sharemation.com/IstvanV/v4l/xc4000fw.c diff -r -d -N -U4 v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c --- v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c 2010-02-11 20:08:39.0 +0100 +++ v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c 2010-02-11 20:05:01.0 +0100 @@ -27,8 +27,9 @@ #include linux/videodev2.h #include linux/delay.h #include linux/dvb/frontend.h #include linux/i2c.h +#include linux/mutex.h #include asm/unaligned.h #include dvb_frontend.h @@ -61,9 +62,9 @@ The valid values are a sum of:\n 1: use NICAM/B and A2/B instead of NICAM/A and A2/A\n 2: use A2 instead of NICAM or BTSC\n 4: use SECAM/K3 instead of K1\n - 8: force SECAM-L audio\n + 8: use PAL-D/K audio for SECAM-D/K\n 16: use FM radio input 1 instead of input 2\n 32: use mono audio (the lower three bits are ignored)\n); #define XC4000_DEFAULT_FIRMWARE xc4000.fw @@ -108,18 +109,20 @@ u32 bandwidth; u8 video_standard; u8 rf_mode; u8 card_type; + u8 ignore_i2c_write_errors; /* struct xc2028_ctrl ctrl; */ struct firmware_properties cur_fw; __u16 hwmodel; __u16 hwvers; - u8 ignore_i2c_write_errors; + struct mutex lock; }; /* Misc Defines */ #define MAX_TV_STANDARD 24 #define XC_MAX_I2C_WRITE_LENGTH 64 +#define XC_POWERED_DOWN 0x8000U /* Signal Types */ #define XC_RF_MODE_AIR 0 #define XC_RF_MODE_CABLE 1 @@ -240,9 +243,9 @@ {D/K-PAL-MONO, 0x0078, 0x8049, 6500}, {D/K-SECAM-A2 DK1, 0x, 0x8049, 6340}, {D/K-SECAM-A2 L/DK3, 0x, 0x8049, 6000}, {D/K-SECAM-A2 MONO, 0x0078, 0x8049, 6500}, - {D/K-SECAM-NICAM, 0x8080, 0x8049, 6200}, + {D/K-SECAM-NICAM, 0x0080, 0x8049, 6200}, {L-SECAM-NICAM, 0x8080, 0x0009, 6200}, {L'-SECAM-NICAM, 0x8080, 0x4009, 6200}, {DTV6, 0x00C0, 0x8002,0}, {DTV8, 0x00C0, 0x800B,0}, @@ -251,11 +254,8 @@ {FM Radio-INPUT2, 0x0008, 0x9800,10700}, {FM Radio-INPUT1, 0x0008, 0x9000,10700} }; -#if 0 -static int xc4000_is_firmware_loaded(struct dvb_frontend *fe); -#endif static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val); static int xc4000_TunerReset(struct dvb_frontend *fe); static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) @@ -275,25 +275,8 @@ } return XC_RESULT_SUCCESS; } -/* This routine is never used because the only time we read data from the - i2c bus is when we read registers, and we want that to be an atomic i2c - transaction in case we are on a multi-master bus */ -#if 0 -static int xc_read_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) -{ - struct i2c_msg msg = { .addr = priv-i2c_props.addr, - .flags = I2C_M_RD, .buf = buf, .len = len }; - - if (i2c_transfer(priv-i2c_props.adap, msg, 1) != 1) { - printk(KERN_ERR xc4000 I2C read failed (len=%i)\n, len); - return -EREMOTEIO; - } - return 0; -} -#endif - static void xc_wait(int wait_ms) { msleep(wait_ms); } @@ -444,17 +427,8 @@ only be used for fast scanning for channel lock) */ return xc_write_reg(priv, XREG_RF_FREQ, freq_code); /* WAS: XREG_FINERFREQ */ } -#if 0 -/* We'll probably need these for analog support */ -static int xc_set_Xtal_frequency(struct xc4000_priv *priv, u32 xtalFreqInKHz) -{ - u16 xtalRatio = (32000 * 0x8000)/xtalFreqInKHz; - return xc_write_reg(priv, XREG_XTALFREQ, xtalRatio); -} -#endif - static int xc_get_ADC_Envelope(struct xc4000_priv *priv, u16 *adc_envelope) { return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope); } @@ -1134,8 +1108,11 @@ u16 quality; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; + if (!(priv-cur_fw.type BASE)) + return; + /* Wait for stats to stabilize. * Frame Lines needs two frame times after initial lock * before it is valid. */ @@ -1174,12 +1151,14 @@ struct dvb_frontend_parameters *params) { struct
Re: DTV2000 H Plus issues
I have an updated version now, with these changes: - the firmware file name can be specified with the firmware_name module parameter; it defaults to xc4000.fw - there is another new module parameter (audio_std) for configuring the audio standard (NICAM, A2, etc.), and switching FM radio to using input 1 (i.e. cable TV instead of FM antenna). This is an integer value which can be the sum of: 1: use NICAM/B or A2/B instead of NICAM/A or A2/A 2: use A2 instead of NICAM or BTSC 4: use SECAM K3 instead of K1 8: in SECAM D/K mode, set the IF frequency and audio mode as for SECAM-L (this hack fixed the one SECAM channel I can receive) 16: use FM radio input 1 instead of input 2 32: mono TV audio (does not seem to work, so it is useless) - struct xc4000_config has a new member (card_type) for specifying the card type - some code changes to allow for loading the new firmware files below In addition to analog TV and FM radio, I have tested the IR as well, and it apparently works. DVB-T is still untested, however. There are two separate patches for v4l-dvb revision 28f5eca12bb0: the first one adds the XC4000 driver, while the second one adds support for the Leadtek WinFast DTV2000H Plus card in the CX88 driver. http://www.sharemation.com/IstvanV/v4l/xc4000-28f5eca12bb0.patch http://www.sharemation.com/IstvanV/v4l/cx88-dtv2000h+-28f5eca12bb0.patch These new firmware files are more complete than the previous ones, but are not compatible with the original driver. Both version 1.2 and 1.4 are available: http://www.sharemation.com/IstvanV/v4l/xc4000-1.2.fw http://www.sharemation.com/IstvanV/v4l/xc4000-1.4.fw Note that the 1.4 firmware could have two different versions of DTV6, which only differ in the audio mode register: 0x8002 (as in v1.2) vs. 0x8003. However, the above file includes only the latter one. The following simple utility was used for creating the firmware files. It can extract the firmware data from a Windows driver file (e.g. hcw85bda.sys from Hauppauge, wfeaglxt.sys from Leadtek, etc.; dvb7700all.sys from Pinnacle will not work, however), and supports both v1.2 and v1.4 firmware. The tables at the beginning of the code are not necessarily fully correct, though, and may need some fixing. http://www.sharemation.com/IstvanV/v4l/xc4000fw.c On 01/07/2010 08:49 PM, istva...@mailbox.hu wrote: On 01/05/2010 02:25 AM, Raena Lea-Shannon wrote: Thanks. Will try again later. By the way, for those who would like to test it, here is a patch based on Devin Heitmueller's XC4000 driver and Mirek Slugen's older patch, that adds support for this card: http://www.sharemation.com/IstvanV/v4l/dtv2000h+.patch It can be applied to this version of the v4l-dvb code: http://linuxtv.org/hg/v4l-dvb/archive/75c97b2d1a2a.tar.bz2 This is experimental code, so use it at your own risk. The analogue parts (TV and FM radio) basically work, although there are some minor issues to be fixed. Digital TV is not tested yet, but is theoretically implemented; reports on whether it actually works are welcome. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: DTV2000 H Plus issues
On 01/07/2010 09:00 PM, Devin Heitmueller wrote: Could you please do me a favor and rename your firmware file, both in the patch and the file you are redistributing (perhaps as dvb-fe-xc4000-1.4.1-istanv.fw)? I worry that by redistributing a file with the exact same name as the official release, people are going to get confused and it will make it harder for me to debug problems given my assumptions about what firmware image they are using is incorrect. OK, I have renamed the firmware file. The download links are now: http://www.sharemation.com/IstvanV/v4l/dtv2000h+.patch http://www.sharemation.com/IstvanV/v4l/xc4000-dtv2000hp-1.4.1.fw -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: DTV2000 H Plus issues
On 01/03/2010 09:21 AM, Raena Lea-Shannon wrote: That seems odd. This patch on the LinuxTv site http://www.linuxtv.org/pipermail/linux-dvb/2008-June/026379.html seems to be using the cx88 drivers? Unfortunately, this patch is for the older DTV 2000H (not Plus) card, which uses a Philips FMD1216 tuner. The main change on the Plus card is the replacement of the tuner with the XC4000, and that is why it is not supported yet. However, an XC4000 driver is already under development, and - compiling V4L from source - you could get the card working in the near future. In fact, code that implements support for this card already exists, but it is only for development/testing at the moment. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: DTV2000 H Plus issues
On 01/02/2010 05:10 PM, Raena Lea-Shannon wrote: I have 2 TV Cards. The DTV2000 H Plus and a Technisat. The Technisat works very well. I am trying to get the DVT working for other video input devices such as VCR to make copies of old Videos and an inteface for my N95 video out. I do not seem to be able to get it to find a tuner. Seems to be problem finding the card. Any suggestions wold be greatly appreciated. This card uses an Xceive XC4000 tuner, which is not supported yet. However, a driver for the tuner chip is being developed at kernellabs.com, so the card may become supported in the future. -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Newbie question about choosing a TV tuner card for Linux
Hi! Can someone give me advice on which of these PCI TV tuner cards I should buy for use on Linux ? All are from a similar price range, but I do not know how they compare in terms of Linux support and picture quality. - Leadtek DTV 1800H A relatively cheap card based on CX2388x and XC3028 (?). I read it is a good value for the price, and may be supported on Linux, although some tricks/patches could be needed to get it to work. - Leadtek DTV 2000H Similar to the above card, but is an older model, the tuner is an FMD1216 in a tin can, and it is somewhat more expensive. Is that only because of more bundled Windows software, or is the different tuner a better one quality-wise ? How does the Linux support compare ? - AVerMedia Hybrid PCI+FM (A16AR or A16D) I think the cards currently available with this name are the newer A16D version, which uses SAA713x and XC3028. I would assume it is not a better card than the DTV 1800H, but the SAA713x is better supported on Linux ? - AVerMedia Studio 703 (M17H) This is an analogue-only card (not necessarily a problem, since not many DVB-T channels can be received where I live), and the only information I found about it is that it uses a Philips/NXP chipset. It is not included in the CARDLIST files of the kernel, so maybe it is not supported on Linux ? -- To unsubscribe from this list: send the line unsubscribe linux-media in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html