From 39ce61a846c8e1fa00cb57ad5af021542e6e8403 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 11 Nov 2011 12:46:23 -0200 Subject: [media] dvb: Allow select between DVB-C Annex A and Annex C DVB-C, as defined by ITU-T J.83 has 3 annexes. The differences between Annex A and Annex C is that Annex C uses a subset of the modulation types, and uses a different rolloff factor. A different rolloff means that the bandwidth required is slicely different, and may affect the saw filter configuration at the tuners. Also, some demods have different configurations, depending on using Annex A or Annex C. So, allow userspace to specify it, by changing the rolloff factor. Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/frontend.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 1b1094c35e4f..d9251df867b5 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -329,6 +329,8 @@ typedef enum fe_rolloff { ROLLOFF_20, ROLLOFF_25, ROLLOFF_AUTO, + ROLLOFF_15, /* DVB-C Annex A */ + ROLLOFF_13, /* DVB-C Annex C */ } fe_rolloff_t; typedef enum fe_delivery_system { -- cgit From ba2780c796badfc3741c7cb499a575ca49f17e6d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sun, 13 Nov 2011 18:47:44 -0300 Subject: [media] DVB: Query DVB frontend delivery capabilities Currently, for any multi-standard frontend it is assumed that it just has a single standard capability. This is fine in some cases, but makes things hard when there are incompatible standards in conjuction. Eg: DVB-S can be seen as a subset of DVB-S2, but the same doesn't hold the same for DSS. This is not specific to any driver as it is, but a generic issue. This was handled correctly in the multiproto tree, while such functionality is missing from the v5 API update. http://www.linuxtv.org/pipermail/vdr/2008-November/018417.html Later on a FE_CAN_2G_MODULATION was added as a hack to workaround this issue in the v5 API, but that hack is incapable of addressing the issue, as it can be used to simply distinguish between DVB-S and DVB-S2 alone, or another X vs X2 modulation. If there are more systems, then you have a potential issue. An application needs to query the device capabilities before requesting any operation from the device. Signed-off-by: Manu Abraham Acked-by: Andreas Oberritter Acked-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 36 +++++++++++++++++++++++++++++++ include/linux/dvb/frontend.h | 4 +++- include/linux/dvb/version.h | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index c849455458ea..821b2250ec70 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -974,6 +974,8 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0), _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0), _DTV_CMD(DTV_HIERARCHY, 0, 0), + + _DTV_CMD(DTV_ENUM_DELSYS, 0, 0), }; static void dtv_property_dump(struct dtv_property *tvp) @@ -1209,6 +1211,37 @@ static int dvb_frontend_ioctl_legacy(struct file *file, static int dvb_frontend_ioctl_properties(struct file *file, unsigned int cmd, void *parg); +static void dtv_set_default_delivery_caps(const struct dvb_frontend *fe, struct dtv_property *p) +{ + const struct dvb_frontend_info *info = &fe->ops.info; + u32 ncaps = 0; + + switch (info->type) { + case FE_QPSK: + p->u.buffer.data[ncaps++] = SYS_DVBS; + if (info->caps & FE_CAN_2G_MODULATION) + p->u.buffer.data[ncaps++] = SYS_DVBS2; + if (info->caps & FE_CAN_TURBO_FEC) + p->u.buffer.data[ncaps++] = SYS_TURBO; + break; + case FE_QAM: + p->u.buffer.data[ncaps++] = SYS_DVBC_ANNEX_AC; + break; + case FE_OFDM: + p->u.buffer.data[ncaps++] = SYS_DVBT; + if (info->caps & FE_CAN_2G_MODULATION) + p->u.buffer.data[ncaps++] = SYS_DVBT2; + break; + case FE_ATSC: + if (info->caps & (FE_CAN_8VSB | FE_CAN_16VSB)) + p->u.buffer.data[ncaps++] = SYS_ATSC; + if (info->caps & (FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256)) + p->u.buffer.data[ncaps++] = SYS_DVBC_ANNEX_B; + break; + } + p->u.buffer.len = ncaps; +} + static int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, struct file *file) @@ -1229,6 +1262,9 @@ static int dtv_property_process_get(struct dvb_frontend *fe, } switch(tvp->cmd) { + case DTV_ENUM_DELSYS: + dtv_set_default_delivery_caps(fe, tvp); + break; case DTV_FREQUENCY: tvp->u.data = c->frequency; break; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index d9251df867b5..cb114f52ccf7 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -316,7 +316,9 @@ struct dvb_frontend_event { #define DTV_DVBT2_PLP_ID 43 -#define DTV_MAX_COMMAND DTV_DVBT2_PLP_ID +#define DTV_ENUM_DELSYS 44 + +#define DTV_MAX_COMMAND DTV_ENUM_DELSYS typedef enum fe_pilot { PILOT_ON, diff --git a/include/linux/dvb/version.h b/include/linux/dvb/version.h index 66594b1d5d7b..0559e2bd38f9 100644 --- a/include/linux/dvb/version.h +++ b/include/linux/dvb/version.h @@ -24,6 +24,6 @@ #define _DVBVERSION_H_ #define DVB_API_VERSION 5 -#define DVB_API_VERSION_MINOR 4 +#define DVB_API_VERSION_MINOR 5 #endif /*_DVBVERSION_H_*/ -- cgit From a597fa78d374c57dcf9a9bac02472a530cd7e60a Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 10 Jun 2011 12:23:30 -0300 Subject: [media] v4l: Add over-current and indicator flash fault bits Flash controllers can report over-current and indicator fault conditions. Define flash fault control bits for them. Signed-off-by: Laurent Pinchart Acked-by: Andy Shevchenko Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/controls.xml | 10 ++++++++++ include/linux/videodev2.h | 2 ++ 2 files changed, 12 insertions(+) (limited to 'include/linux') diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index 9e72f077329a..c0422c622337 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -3329,6 +3329,16 @@ interface and may change in the future. The short circuit protection of the flash controller has been triggered. + + V4L2_FLASH_FAULT_OVER_CURRENT + Current in the LED power supply has exceeded the limit + specific to the flash controller. + + + V4L2_FLASH_FAULT_INDICATOR + The flash controller has detected a short or open + circuit condition on the indicator LED. + diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 4b752d5ee80e..3d62631839bc 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1682,6 +1682,8 @@ enum v4l2_flash_strobe_source { #define V4L2_FLASH_FAULT_TIMEOUT (1 << 1) #define V4L2_FLASH_FAULT_OVER_TEMPERATURE (1 << 2) #define V4L2_FLASH_FAULT_SHORT_CIRCUIT (1 << 3) +#define V4L2_FLASH_FAULT_OVER_CURRENT (1 << 4) +#define V4L2_FLASH_FAULT_INDICATOR (1 << 5) #define V4L2_CID_FLASH_CHARGE (V4L2_CID_FLASH_CLASS_BASE + 11) #define V4L2_CID_FLASH_READY (V4L2_CID_FLASH_CLASS_BASE + 12) -- cgit From bf3b84006e22ae241ec3d53dbe6c6d1f6ceddb56 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 17 Dec 2011 20:36:55 -0300 Subject: [media] DVB: Use a unique delivery system identifier for DVBC_ANNEX_C Use a unique delivery system identifier for DVBC_ANNEX_C, just like any other. DVBC_ANNEX_A and DVBC_ANNEX_C have slightly different parameters and are used in 2 geographically different locations. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/frontend.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index cb114f52ccf7..b2a939f8f1e2 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -337,7 +337,7 @@ typedef enum fe_rolloff { typedef enum fe_delivery_system { SYS_UNDEFINED, - SYS_DVBC_ANNEX_AC, + SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_B, SYS_DVBT, SYS_DSS, @@ -354,8 +354,13 @@ typedef enum fe_delivery_system { SYS_DAB, SYS_DVBT2, SYS_TURBO, + SYS_DVBC_ANNEX_C, } fe_delivery_system_t; + +#define SYS_DVBC_ANNEX_AC SYS_DVBC_ANNEX_A + + struct dtv_cmds_h { char *name; /* A display name for debugging purposes */ -- cgit From fd66c45dd51000ff444231a94ac15ccab8cffd3d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 17 Dec 2011 20:36:57 -0300 Subject: [media] Remove Annex A/C selection via roll-off factor Instead of using a roll-off factor, change DRX-K & friends to select the bandwidth filter and the Nyquist half roll-off via delivery system. This provides a cleaner support for Annex A/C switch. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 137 ++++++++++++----------------- drivers/media/dvb/dvb-core/dvb_frontend.c | 25 +++++- drivers/media/dvb/frontends/drxk_hard.c | 15 ++-- drivers/media/dvb/frontends/tda18271c2dd.c | 44 ++++----- include/linux/dvb/frontend.h | 2 - 5 files changed, 106 insertions(+), 117 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 97ad33896343..5c56d3cc030b 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -629,11 +629,13 @@ static void xc_debug_dump(struct xc5000_priv *priv) } static int xc5000_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) + struct dvb_frontend_parameters *params) { + int ret, b; struct xc5000_priv *priv = fe->tuner_priv; - int ret; - u32 bw; + u32 bw = fe->dtv_property_cache.bandwidth_hz; + u32 freq = fe->dtv_property_cache.frequency; + u32 delsys = fe->dtv_property_cache.delivery_system; if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) { @@ -642,104 +644,77 @@ static int xc5000_set_params(struct dvb_frontend *fe, } } - dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency); + dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq); - if (fe->ops.info.type == FE_ATSC) { - dprintk(1, "%s() ATSC\n", __func__); - switch (params->u.vsb.modulation) { - case VSB_8: - case VSB_16: - dprintk(1, "%s() VSB modulation\n", __func__); - priv->rf_mode = XC_RF_MODE_AIR; - priv->freq_hz = params->frequency - 1750000; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - break; - case QAM_64: - case QAM_256: - case QAM_AUTO: - dprintk(1, "%s() QAM modulation\n", __func__); - priv->rf_mode = XC_RF_MODE_CABLE; - priv->freq_hz = params->frequency - 1750000; - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - break; - default: - return -EINVAL; - } - } else if (fe->ops.info.type == FE_OFDM) { + switch (delsys) { + case SYS_ATSC: + dprintk(1, "%s() VSB modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_AIR; + priv->freq_hz = freq - 1750000; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + break; + case SYS_DVBC_ANNEX_B: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; + priv->freq_hz = freq - 1750000; + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + break; + case SYS_DVBT: + case SYS_DVBT2: dprintk(1, "%s() OFDM\n", __func__); - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: + switch (bw) { + case 6000000: priv->bandwidth = BANDWIDTH_6_MHZ; priv->video_standard = DTV6; - priv->freq_hz = params->frequency - 1750000; + priv->freq_hz = freq - 1750000; break; - case BANDWIDTH_7_MHZ: + case 7000000: priv->bandwidth = BANDWIDTH_7_MHZ; priv->video_standard = DTV7; - priv->freq_hz = params->frequency - 2250000; + priv->freq_hz = freq - 2250000; break; - case BANDWIDTH_8_MHZ: + case 8000000: priv->bandwidth = BANDWIDTH_8_MHZ; priv->video_standard = DTV8; - priv->freq_hz = params->frequency - 2750000; + priv->freq_hz = freq - 2750000; break; default: printk(KERN_ERR "xc5000 bandwidth not set!\n"); return -EINVAL; } priv->rf_mode = XC_RF_MODE_AIR; - } else if (fe->ops.info.type == FE_QAM) { - switch (params->u.qam.modulation) { - case QAM_256: - case QAM_AUTO: - case QAM_16: - case QAM_32: - case QAM_64: - case QAM_128: - dprintk(1, "%s() QAM modulation\n", __func__); - priv->rf_mode = XC_RF_MODE_CABLE; - /* - * Using a higher bandwidth at the tuner filter may - * allow inter-carrier interference. - * So, determine the minimal channel spacing, in order - * to better adjust the tuner filter. - * According with ITU-T J.83, the bandwidth is given by: - * bw = Simbol Rate * (1 + roll_off), where the roll_off - * is equal to 0.15 for Annex A, and 0.13 for annex C - */ - if (fe->dtv_property_cache.rolloff == ROLLOFF_13) - bw = (params->u.qam.symbol_rate * 113) / 100; - else - bw = (params->u.qam.symbol_rate * 115) / 100; - if (bw <= 6000000) { - priv->bandwidth = BANDWIDTH_6_MHZ; - priv->video_standard = DTV6; - priv->freq_hz = params->frequency - 1750000; - } else if (bw <= 7000000) { - priv->bandwidth = BANDWIDTH_7_MHZ; - priv->video_standard = DTV7; - priv->freq_hz = params->frequency - 2250000; - } else { - priv->bandwidth = BANDWIDTH_8_MHZ; - priv->video_standard = DTV7_8; - priv->freq_hz = params->frequency - 2750000; - } - dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__, - BANDWIDTH_6_MHZ ? 6: 8, bw); - break; - default: - dprintk(1, "%s() Unsupported QAM type\n", __func__); - return -EINVAL; + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: + dprintk(1, "%s() QAM modulation\n", __func__); + priv->rf_mode = XC_RF_MODE_CABLE; + if (bw <= 6000000) { + priv->bandwidth = BANDWIDTH_6_MHZ; + priv->video_standard = DTV6; + priv->freq_hz = freq - 1750000; + b = 6; + } else if (bw <= 7000000) { + priv->bandwidth = BANDWIDTH_7_MHZ; + priv->video_standard = DTV7; + priv->freq_hz = freq - 2250000; + b = 7; + } else { + priv->bandwidth = BANDWIDTH_8_MHZ; + priv->video_standard = DTV7_8; + priv->freq_hz = freq - 2750000; + b = 8; } - } else { - printk(KERN_ERR "xc5000 modulation type not supported!\n"); + dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__, + b, bw); + break; + default: + printk(KERN_ERR "xc5000: delivery system is not supported!\n"); return -EINVAL; } - dprintk(1, "%s() frequency=%d (compensated)\n", - __func__, priv->freq_hz); + dprintk(1, "%s() frequency=%d (compensated to %d)\n", + __func__, freq, priv->freq_hz); ret = xc_SetSignalSource(priv, priv->rf_mode); if (ret != XC_RESULT_SUCCESS) { diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 821b2250ec70..66537b10132c 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1011,7 +1011,7 @@ static void dtv_property_dump(struct dtv_property *tvp) static int is_legacy_delivery_system(fe_delivery_system_t s) { - if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || + if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_A) || (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) || (s == SYS_ATSC)) return 1; @@ -1032,8 +1032,7 @@ static void dtv_property_cache_init(struct dvb_frontend *fe, c->delivery_system = SYS_DVBS; break; case FE_QAM: - c->delivery_system = SYS_DVBC_ANNEX_AC; - c->rolloff = ROLLOFF_15; /* implied for Annex A */ + c->delivery_system = SYS_DVBC_ANNEX_A; break; case FE_OFDM: c->delivery_system = SYS_DVBT; @@ -1144,9 +1143,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) */ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) { - const struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; struct dvb_frontend_parameters *p = &fepriv->parameters_in; + u32 rolloff = 0; p->frequency = c->frequency; p->inversion = c->inversion; @@ -1178,6 +1178,23 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) else p->u.ofdm.bandwidth = BANDWIDTH_AUTO; } + + /* + * On DVB-C, the bandwidth is a function of roll-off and symbol rate. + * The bandwidth is required for DVB-C tuners, in order to avoid + * inter-channel noise. Instead of estimating the minimal required + * bandwidth on every single driver, calculates it here and fills + * it at the cache bandwidth parameter. + * While not officially supported, a side effect of handling it at + * the cache level is that a program could retrieve the bandwidth + * via DTV_BANDWIDTH_HZ, wich may be useful for test programs. + */ + if (c->delivery_system == SYS_DVBC_ANNEX_A) + rolloff = 115; + if (c->delivery_system == SYS_DVBC_ANNEX_C) + rolloff = 113; + if (rolloff) + c->bandwidth_hz = (c->symbol_rate * rolloff) / 100; } static void dtv_property_cache_submit(struct dvb_frontend *fe) diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c index 038e470bf039..a2c819651933 100644 --- a/drivers/media/dvb/frontends/drxk_hard.c +++ b/drivers/media/dvb/frontends/drxk_hard.c @@ -6215,6 +6215,7 @@ static int drxk_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { struct drxk_state *state = fe->demodulator_priv; + u32 delsys = fe->dtv_property_cache.delivery_system; u32 IF; dprintk(1, "\n"); @@ -6225,11 +6226,15 @@ static int drxk_set_parameters(struct dvb_frontend *fe, return -EINVAL; } - if (fe->ops.info.type == FE_QAM) { - if (fe->dtv_property_cache.rolloff == ROLLOFF_13) - state->m_itut_annex_c = true; - else - state->m_itut_annex_c = false; + switch (delsys) { + case SYS_DVBC_ANNEX_A: + state->m_itut_annex_c = false; + break; + case SYS_DVBC_ANNEX_C: + state->m_itut_annex_c = true; + break; + default: + return -EINVAL; } if (fe->ops.i2c_gate_ctrl) diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c index b66ca29704fc..0f8e9622bc96 100644 --- a/drivers/media/dvb/frontends/tda18271c2dd.c +++ b/drivers/media/dvb/frontends/tda18271c2dd.c @@ -1130,50 +1130,44 @@ static int set_params(struct dvb_frontend *fe, struct tda_state *state = fe->tuner_priv; int status = 0; int Standard; - u32 bw; + u32 bw = fe->dtv_property_cache.bandwidth_hz; + u32 delsys = fe->dtv_property_cache.delivery_system; - state->m_Frequency = params->frequency; + state->m_Frequency = fe->dtv_property_cache.frequency; - if (fe->ops.info.type == FE_OFDM) - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: + switch (delsys) { + case SYS_DVBT: + case SYS_DVBT2: + switch (bw) { + case 6000000: Standard = HF_DVBT_6MHZ; break; - case BANDWIDTH_7_MHZ: + case 7000000: Standard = HF_DVBT_7MHZ; break; - default: - case BANDWIDTH_8_MHZ: + case 8000000: Standard = HF_DVBT_8MHZ; break; + default: + return -EINVAL; } - else if (fe->ops.info.type == FE_QAM) { - /* - * Using a higher bandwidth at the tuner filter may - * allow inter-carrier interference. - * So, determine the minimal channel spacing, in order - * to better adjust the tuner filter. - * According with ITU-T J.83, the bandwidth is given by: - * bw = Simbol Rate * (1 + roll_off), where the roll_off - * is equal to 0.15 for Annex A, and 0.13 for annex C - */ - if (fe->dtv_property_cache.rolloff == ROLLOFF_13) - bw = (params->u.qam.symbol_rate * 113) / 100; - else - bw = (params->u.qam.symbol_rate * 115) / 100; + case SYS_DVBC_ANNEX_A: + case SYS_DVBC_ANNEX_C: if (bw <= 6000000) Standard = HF_DVBC_6MHZ; else if (bw <= 7000000) Standard = HF_DVBC_7MHZ; else Standard = HF_DVBC_8MHZ; - } else + default: return -EINVAL; + } do { - status = RFTrackingFiltersCorrection(state, params->frequency); + status = RFTrackingFiltersCorrection(state, state->m_Frequency); if (status < 0) break; - status = ChannelConfiguration(state, params->frequency, Standard); + status = ChannelConfiguration(state, state->m_Frequency, + Standard); if (status < 0) break; diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index b2a939f8f1e2..a3c762383f88 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -331,8 +331,6 @@ typedef enum fe_rolloff { ROLLOFF_20, ROLLOFF_25, ROLLOFF_AUTO, - ROLLOFF_15, /* DVB-C Annex A */ - ROLLOFF_13, /* DVB-C Annex C */ } fe_rolloff_t; typedef enum fe_delivery_system { -- cgit From cc1d327232759647ea56725eab1c6b16c92d52fa Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 14 Nov 2011 08:48:18 -0300 Subject: [media] v4l: Add new alpha component control The V4L2_CID_ALPHA_COMPONENT control is intended for the video capture or memory-to-memory devices that are capable of setting up the per-pixel alpha component to some arbitrary value. It allows to set the alpha component for all pixels to an arbitrary value. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/compat.xml | 11 ++++++++++ Documentation/DocBook/media/v4l/controls.xml | 25 ++++++++++++++++------ .../DocBook/media/v4l/pixfmt-packed-rgb.xml | 7 ++++-- drivers/media/video/v4l2-ctrls.c | 1 + include/linux/videodev2.h | 6 +++--- 5 files changed, 39 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index 8b44a43f4542..12ba26262d32 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2379,6 +2379,17 @@ that used it. It was originally scheduled for removal in 2.6.35. +
+ V4L2 in Linux 3.3 + + + Added V4L2_CID_ALPHA_COMPONENT control + to the User controls class. + + + +
+
Relation of V4L2 to other Linux multimedia APIs diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index c0422c622337..a1be37897ad7 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -323,12 +323,6 @@ minimum value disables backlight compensation. Switch on or off the illuminator 1 or 2 of the device (usually a microscope). - - V4L2_CID_LASTP1 - - End of the predefined control IDs (currently -V4L2_CID_ILLUMINATORS_2 + 1). - V4L2_CID_MIN_BUFFERS_FOR_CAPTURE integer @@ -345,6 +339,25 @@ and used as a hint to determine the number of OUTPUT buffers to pass to REQBUFS. The value is the minimum number of OUTPUT buffers that is necessary for hardware to work. + + V4L2_CID_ALPHA_COMPONENT + integer + Sets the alpha color component on the capture device or on + the capture buffer queue of a mem-to-mem device. When a mem-to-mem + device produces frame format that includes an alpha component + (e.g. packed RGB image formats) + and the alpha value is not defined by the mem-to-mem input data + this control lets you select the alpha component value of all + pixels. It is applicable to any pixel format that contains an alpha + component. + + + + V4L2_CID_LASTP1 + + End of the predefined control IDs (currently + V4L2_CID_ALPHA_COMPONENT + 1). + V4L2_CID_PRIVATE_BASE diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml index ba56536622f2..166c8d65e4f7 100644 --- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml +++ b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml @@ -428,8 +428,11 @@ colorspace V4L2_COLORSPACE_SRGB. Bit 7 is the most significant bit. The value of a = alpha bits is undefined when reading from the driver, ignored when writing to the driver, except when alpha blending has been negotiated for a -Video Overlay or Video Output Overlay. +Video Overlay or +Video Output Overlay or when alpha component has been configured +for a Video Capture by means of V4L2_CID_ALPHA_COMPONENT + control. <constant>V4L2_PIX_FMT_BGR24</constant> 4 × 4 pixel diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 0f415dade05a..39266153499f 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -467,6 +467,7 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2"; case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers"; case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers"; + case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; /* MPEG controls */ /* Keep the order of the 'case's the same as in videodev2.h! */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 3d62631839bc..2965906a02c9 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1204,10 +1204,10 @@ enum v4l2_colorfx { #define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE (V4L2_CID_BASE+39) #define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT (V4L2_CID_BASE+40) -/* last CID + 1 */ -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+41) +#define V4L2_CID_ALPHA_COMPONENT (V4L2_CID_BASE+41) -/* Minimum number of buffer neede by the device */ +/* last CID + 1 */ +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+42) /* MPEG-class control IDs defined by V4L2 */ #define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -- cgit From 8de8594a79ae43b08d115c94f09373f6c673f202 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Mon, 26 Dec 2011 20:22:50 -0300 Subject: [media] dvb-core: be sure that drivers won't use DVBv3 internally Now that all frontends are implementing DVBv5, don't export the DVBv3 specific stuff to the drivers. Only the core should be aware of that, as it will keep providing DVBv3 backward compatibility. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/dvb/dvb-core/dvb_frontend.c | 3 +++ drivers/media/dvb/dvb-core/dvb_frontend.h | 2 ++ include/linux/dvb/frontend.h | 6 ++++-- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index b1ab866743fd..55ca5521bca6 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -25,6 +25,9 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +/* Enables DVBv3 compatibility bits at the headers */ +#define __DVB_CORE__ + #include <linux/string.h> #include <linux/kernel.h> #include <linux/sched.h> diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 93715d6755f4..676481c8ad78 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -315,6 +315,7 @@ struct dvb_frontend_ops { int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); }; +#ifdef __DVB_CORE__ #define MAX_EVENT 8 struct dvb_fe_events { @@ -325,6 +326,7 @@ struct dvb_fe_events { wait_queue_head_t wait_queue; struct mutex mtx; }; +#endif struct dtv_frontend_properties { diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index a3c762383f88..7e7cb64f56d8 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -181,6 +181,7 @@ typedef enum fe_transmit_mode { TRANSMISSION_MODE_32K, } fe_transmit_mode_t; +#if defined(__DVB_CORE__) || !defined (__KERNEL__) typedef enum fe_bandwidth { BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, @@ -190,7 +191,7 @@ typedef enum fe_bandwidth { BANDWIDTH_10_MHZ, BANDWIDTH_1_712_MHZ, } fe_bandwidth_t; - +#endif typedef enum fe_guard_interval { GUARD_INTERVAL_1_32, @@ -213,6 +214,7 @@ typedef enum fe_hierarchy { } fe_hierarchy_t; +#if defined(__DVB_CORE__) || !defined (__KERNEL__) struct dvb_qpsk_parameters { __u32 symbol_rate; /* symbol rate in Symbols per second */ fe_code_rate_t fec_inner; /* forward error correction (see above) */ @@ -251,11 +253,11 @@ struct dvb_frontend_parameters { } u; }; - struct dvb_frontend_event { fe_status_t status; struct dvb_frontend_parameters parameters; }; +#endif /* S2API Commands */ #define DTV_UNDEFINED 0 -- cgit From cd7d494d0b23673215330963c28138dd0c3fd405 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@redhat.com> Date: Sun, 1 Jan 2012 16:11:17 -0300 Subject: [media] dvb: deprecate the usage of ops->info.type Mark info.type as deprecated inside the header, recommending the usage of DTV_ENUM_DELSYS DVBv5 command instead. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- Documentation/DocBook/media/dvb/frontend.xml | 4 ++++ include/linux/dvb/frontend.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/media/dvb/frontend.xml b/Documentation/DocBook/media/dvb/frontend.xml index 28d7ea5d5e73..aeaed59d0f1f 100644 --- a/Documentation/DocBook/media/dvb/frontend.xml +++ b/Documentation/DocBook/media/dvb/frontend.xml @@ -63,6 +63,10 @@ transmission. The fontend types are given by fe_type_t type, defined as:</para> <para>Newer formats like DVB-S2, ISDB-T, ISDB-S and DVB-T2 are not described at the above, as they're supported via the new <link linkend="FE_GET_SET_PROPERTY">FE_GET_PROPERTY/FE_GET_SET_PROPERTY</link> ioctl's, using the <link linkend="DTV-DELIVERY-SYSTEM">DTV_DELIVERY_SYSTEM</link> parameter. </para> + +<para>The usage of this field is deprecated, as it doesn't report all supported standards, and +will provide an incomplete information for frontends that support multiple delivery systems. +Please use <link linkend="DTV_ENUM_DELSYS">DTV_ENUM_DELSYS</link> instead.</para> </section> <section id="fe-caps-t"> diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index 7e7cb64f56d8..cb4428ab81ed 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h @@ -72,7 +72,7 @@ typedef enum fe_caps { struct dvb_frontend_info { char name[128]; - fe_type_t type; + fe_type_t type; /* DEPRECATED. Use DTV_ENUM_DELSYS instead */ __u32 frequency_min; __u32 frequency_max; __u32 frequency_stepsize; -- cgit From fe3449a4aa4e62404cc1c57c945fd56152b2f877 Mon Sep 17 00:00:00 2001 From: Theodore Kilgore <kilgota@banach.math.auburn.edu> Date: Tue, 13 Dec 2011 18:09:15 -0300 Subject: [media] gspca: Add jl2005bcd sub driver Written by Theodore Kilgore With minor changes by Hans de Goede: -Code style fixes -Correct the verbose level on various PDEBUG messages -Make error messages use pr_err instead of PDEBUG -Document the jl20 pixel format Signed-off-by: Theodore Kilgore <kilgota@auburn.edu> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- Documentation/DocBook/media/v4l/pixfmt.xml | 5 + Documentation/video4linux/gspca.txt | 1 + drivers/media/video/gspca/Kconfig | 10 + drivers/media/video/gspca/Makefile | 2 + drivers/media/video/gspca/jl2005bcd.c | 554 +++++++++++++++++++++++++++++ include/linux/videodev2.h | 1 + 6 files changed, 573 insertions(+) create mode 100644 drivers/media/video/gspca/jl2005bcd.c (limited to 'include/linux') diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index a33a4b22173b..9ddc57cb2ef9 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -890,6 +890,11 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm <entry>'M310'</entry> <entry>Compressed BGGR Bayer format used by the gspca driver.</entry> </row> + <row id="V4L2-PIX-FMT-JL2005BCD"> + <entry><constant>V4L2_PIX_FMT_JL2005BCD</constant></entry> + <entry>'JL20'</entry> + <entry>JPEG compressed RGGB Bayer format used by the gspca driver.</entry> + </row> <row id="V4L2-PIX-FMT-OV511"> <entry><constant>V4L2_PIX_FMT_OV511</constant></entry> <entry>'O511'</entry> diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt index 393815b62810..f2060f0dc02c 100644 --- a/Documentation/video4linux/gspca.txt +++ b/Documentation/video4linux/gspca.txt @@ -279,6 +279,7 @@ pac7302 093a:2628 Genius iLook 300 pac7302 093a:2629 Genious iSlim 300 pac7302 093a:262a Webcam 300k pac7302 093a:262c Philips SPC 230 NC +jl2005bcd 0979:0227 Various brands, 19 known cameras supported jeilinj 0979:0280 Sakar 57379 jeilinj 0979:0280 Sportscam DV15 zc3xx 0ac8:0302 Z-star Vimicro zc0302 diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 103af3fe5aa0..dfe268bfa4f8 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -77,6 +77,16 @@ config USB_GSPCA_JEILINJ To compile this driver as a module, choose M here: the module will be called gspca_jeilinj. +config USB_GSPCA_JL2005BCD + tristate "JL2005B/C/D USB V4L2 driver" + depends on VIDEO_V4L2 && USB_GSPCA + help + Say Y here if you want support for cameras based the + JL2005B, JL2005C, or JL2005D chip. + + To compile this driver as a module, choose M here: the + module will be called gspca_jl2005bcd. + config USB_GSPCA_KINECT tristate "Kinect sensor device USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index f345f494d0f3..79ebe46e1ad7 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o +obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o @@ -49,6 +50,7 @@ gspca_cpia1-objs := cpia1.o gspca_etoms-objs := etoms.o gspca_finepix-objs := finepix.o gspca_jeilinj-objs := jeilinj.o +gspca_jl2005bcd-objs := jl2005bcd.o gspca_kinect-objs := kinect.o gspca_konica-objs := konica.o gspca_mars-objs := mars.o diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c new file mode 100644 index 000000000000..53f58ef367cf --- /dev/null +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -0,0 +1,554 @@ +/* + * Jeilin JL2005B/C/D library + * + * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MODULE_NAME "jl2005bcd" + +#include <linux/workqueue.h> +#include <linux/slab.h> +#include "gspca.h" + + +MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); +MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver"); +MODULE_LICENSE("GPL"); + +/* Default timeouts, in ms */ +#define JL2005C_CMD_TIMEOUT 500 +#define JL2005C_DATA_TIMEOUT 1000 + +/* Maximum transfer size to use. */ +#define JL2005C_MAX_TRANSFER 0x200 +#define FRAME_HEADER_LEN 16 + + +/* specific webcam descriptor */ +struct sd { + struct gspca_dev gspca_dev; /* !! must be the first item */ + unsigned char firmware_id[6]; + const struct v4l2_pix_format *cap_mode; + /* Driver stuff */ + struct work_struct work_struct; + struct workqueue_struct *work_thread; + u8 frame_brightness; + int block_size; /* block size of camera */ + int vga; /* 1 if vga cam, 0 if cif cam */ +}; + + +/* Camera has two resolution settings. What they are depends on model. */ +static const struct v4l2_pix_format cif_mode[] = { + {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 176, + .sizeimage = 176 * 144, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 352, + .sizeimage = 352 * 288, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + +static const struct v4l2_pix_format vga_mode[] = { + {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 320, + .sizeimage = 320 * 240, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, + {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, + .bytesperline = 640, + .sizeimage = 640 * 480, + .colorspace = V4L2_COLORSPACE_SRGB, + .priv = 0}, +}; + +/* + * cam uses endpoint 0x03 to send commands, 0x84 for read commands, + * and 0x82 for bulk data transfer. + */ + +/* All commands are two bytes only */ +static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command) +{ + int retval; + + memcpy(gspca_dev->usb_buf, command, 2); + retval = usb_bulk_msg(gspca_dev->dev, + usb_sndbulkpipe(gspca_dev->dev, 3), + gspca_dev->usb_buf, 2, NULL, 500); + if (retval < 0) + pr_err("command write [%02x] error %d\n", + gspca_dev->usb_buf[0], retval); + return retval; +} + +/* Response to a command is one byte in usb_buf[0], only if requested. */ +static int jl2005c_read1(struct gspca_dev *gspca_dev) +{ + int retval; + + retval = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x84), + gspca_dev->usb_buf, 1, NULL, 500); + if (retval < 0) + pr_err("read command [0x%02x] error %d\n", + gspca_dev->usb_buf[0], retval); + return retval; +} + +/* Response appears in gspca_dev->usb_buf[0] */ +static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg) +{ + int retval; + + static u8 instruction[2] = {0x95, 0x00}; + /* put register to read in byte 1 */ + instruction[1] = reg; + /* Send the read request */ + retval = jl2005c_write2(gspca_dev, instruction); + if (retval < 0) + return retval; + retval = jl2005c_read1(gspca_dev); + + return retval; +} + +static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev) +{ + int i; + int retval; + int frame_brightness = 0; + + static u8 instruction[2] = {0x7f, 0x01}; + + retval = jl2005c_write2(gspca_dev, instruction); + if (retval < 0) + return retval; + + i = 0; + while (i < 20 && !frame_brightness) { + /* If we tried 20 times, give up. */ + retval = jl2005c_read_reg(gspca_dev, 0x7e); + if (retval < 0) + return retval; + frame_brightness = gspca_dev->usb_buf[0]; + retval = jl2005c_read_reg(gspca_dev, 0x7d); + if (retval < 0) + return retval; + i++; + } + PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]); + return retval; +} + +static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg, + unsigned char value) +{ + int retval; + u8 instruction[2]; + + instruction[0] = reg; + instruction[1] = value; + + retval = jl2005c_write2(gspca_dev, instruction); + if (retval < 0) + return retval; + + return retval; +} + +static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev) +{ + struct sd *sd = (struct sd *)gspca_dev; + int i = 0; + int retval = -1; + unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f}; + + PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id"); + /* Read the first ID byte once for warmup */ + retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]); + PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]); + if (retval < 0) + return retval; + /* Now actually get the ID string */ + for (i = 0; i < 6; i++) { + retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]); + if (retval < 0) + return retval; + sd->firmware_id[i] = gspca_dev->usb_buf[0]; + } + PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x", + sd->firmware_id[0], + sd->firmware_id[1], + sd->firmware_id[2], + sd->firmware_id[3], + sd->firmware_id[4], + sd->firmware_id[5]); + return 0; +} + +static int jl2005c_stream_start_vga_lg + (struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x05, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x18}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x52}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + +static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x06, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x1a}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x52}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + +static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x05, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x30}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x42}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + +static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev) +{ + int i; + int retval = -1; + static u8 instruction[][2] = { + {0x06, 0x00}, + {0x7c, 0x00}, + {0x7d, 0x32}, + {0x02, 0x00}, + {0x01, 0x00}, + {0x04, 0x42}, + }; + + for (i = 0; i < ARRAY_SIZE(instruction); i++) { + msleep(60); + retval = jl2005c_write2(gspca_dev, instruction[i]); + if (retval < 0) + return retval; + } + msleep(60); + return retval; +} + + +static int jl2005c_stop(struct gspca_dev *gspca_dev) +{ + int retval; + + retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00); + return retval; +} + +/* This function is called as a workqueue function and runs whenever the camera + * is streaming data. Because it is a workqueue function it is allowed to sleep + * so we can use synchronous USB calls. To avoid possible collisions with other + * threads attempting to use the camera's USB interface the gspca usb_lock is + * used when performing the one USB control operation inside the workqueue, + * which tells the camera to close the stream. In practice the only thing + * which needs to be protected against is the usb_set_interface call that + * gspca makes during stream_off. Otherwise the camera doesn't provide any + * controls that the user could try to change. + */ +static void jl2005c_dostream(struct work_struct *work) +{ + struct sd *dev = container_of(work, struct sd, work_struct); + struct gspca_dev *gspca_dev = &dev->gspca_dev; + int bytes_left = 0; /* bytes remaining in current frame. */ + int data_len; /* size to use for the next read. */ + int header_read = 0; + unsigned char header_sig[2] = {0x4a, 0x4c}; + int act_len; + int packet_type; + int ret; + u8 *buffer; + + buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); + if (!buffer) { + pr_err("Couldn't allocate USB buffer\n"); + goto quit_stream; + } + + while (gspca_dev->present && gspca_dev->streaming) { + /* Check if this is a new frame. If so, start the frame first */ + if (!header_read) { + mutex_lock(&gspca_dev->usb_lock); + ret = jl2005c_start_new_frame(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + if (ret < 0) + goto quit_stream; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, JL2005C_MAX_TRANSFER, &act_len, + JL2005C_DATA_TIMEOUT); + PDEBUG(D_PACK, + "Got %d bytes out of %d for header", + act_len, JL2005C_MAX_TRANSFER); + if (ret < 0 || act_len < JL2005C_MAX_TRANSFER) + goto quit_stream; + /* Check whether we actually got the first blodk */ + if (memcmp(header_sig, buffer, 2) != 0) { + pr_err("First block is not the first block\n"); + goto quit_stream; + } + /* total size to fetch is byte 7, times blocksize + * of which we already got act_len */ + bytes_left = buffer[0x07] * dev->block_size - act_len; + PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left); + /* We keep the header. It has other information, too.*/ + packet_type = FIRST_PACKET; + gspca_frame_add(gspca_dev, packet_type, + buffer, act_len); + header_read = 1; + } + while (bytes_left > 0 && gspca_dev->present) { + data_len = bytes_left > JL2005C_MAX_TRANSFER ? + JL2005C_MAX_TRANSFER : bytes_left; + ret = usb_bulk_msg(gspca_dev->dev, + usb_rcvbulkpipe(gspca_dev->dev, 0x82), + buffer, data_len, &act_len, + JL2005C_DATA_TIMEOUT); + if (ret < 0 || act_len < data_len) + goto quit_stream; + PDEBUG(D_PACK, + "Got %d bytes out of %d for frame", + data_len, bytes_left); + bytes_left -= data_len; + if (bytes_left == 0) { + packet_type = LAST_PACKET; + header_read = 0; + } else + packet_type = INTER_PACKET; + gspca_frame_add(gspca_dev, packet_type, + buffer, data_len); + } + } +quit_stream: + if (gspca_dev->present) { + mutex_lock(&gspca_dev->usb_lock); + jl2005c_stop(gspca_dev); + mutex_unlock(&gspca_dev->usb_lock); + } + kfree(buffer); +} + + + + +/* This function is called at probe time */ +static int sd_config(struct gspca_dev *gspca_dev, + const struct usb_device_id *id) +{ + struct cam *cam; + struct sd *sd = (struct sd *) gspca_dev; + + cam = &gspca_dev->cam; + /* We don't use the buffer gspca allocates so make it small. */ + cam->bulk_size = 64; + cam->bulk = 1; + /* For the rest, the camera needs to be detected */ + jl2005c_get_firmware_id(gspca_dev); + /* Here are some known firmware IDs + * First some JL2005B cameras + * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam + * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B + * JL2005C cameras + * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512 + * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly + * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz + * + * Based upon this scanty evidence, we can detect a CIF camera by + * testing byte 0 for 0x4x. + */ + if ((sd->firmware_id[0] & 0xf0) == 0x40) { + cam->cam_mode = cif_mode; + cam->nmodes = ARRAY_SIZE(cif_mode); + sd->block_size = 0x80; + } else { + cam->cam_mode = vga_mode; + cam->nmodes = ARRAY_SIZE(vga_mode); + sd->block_size = 0x200; + } + + INIT_WORK(&sd->work_struct, jl2005c_dostream); + + return 0; +} + +/* this function is called at probe and resume time */ +static int sd_init(struct gspca_dev *gspca_dev) +{ + return 0; +} + +static int sd_start(struct gspca_dev *gspca_dev) +{ + + struct sd *sd = (struct sd *) gspca_dev; + sd->cap_mode = gspca_dev->cam.cam_mode; + + switch (gspca_dev->width) { + case 640: + PDEBUG(D_STREAM, "Start streaming at vga resolution"); + jl2005c_stream_start_vga_lg(gspca_dev); + break; + case 320: + PDEBUG(D_STREAM, "Start streaming at qvga resolution"); + jl2005c_stream_start_vga_small(gspca_dev); + break; + case 352: + PDEBUG(D_STREAM, "Start streaming at cif resolution"); + jl2005c_stream_start_cif_lg(gspca_dev); + break; + case 176: + PDEBUG(D_STREAM, "Start streaming at qcif resolution"); + jl2005c_stream_start_cif_small(gspca_dev); + break; + default: + pr_err("Unknown resolution specified\n"); + return -1; + } + + /* Start the workqueue function to do the streaming */ + sd->work_thread = create_singlethread_workqueue(MODULE_NAME); + queue_work(sd->work_thread, &sd->work_struct); + + return 0; +} + +/* called on streamoff with alt==0 and on disconnect */ +/* the usb_lock is held at entry - restore on exit */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct sd *dev = (struct sd *) gspca_dev; + + /* wait for the work queue to terminate */ + mutex_unlock(&gspca_dev->usb_lock); + /* This waits for sq905c_dostream to finish */ + destroy_workqueue(dev->work_thread); + dev->work_thread = NULL; + mutex_lock(&gspca_dev->usb_lock); +} + + + +/* sub-driver description */ +static const struct sd_desc sd_desc = { + .name = MODULE_NAME, + /* .ctrls = none have been detected */ + /* .nctrls = ARRAY_SIZE(sd_ctrls), */ + .config = sd_config, + .init = sd_init, + .start = sd_start, + .stop0 = sd_stop0, +}; + +/* -- module initialisation -- */ +static const __devinitdata struct usb_device_id device_table[] = { + {USB_DEVICE(0x0979, 0x0227)}, + {} +}; +MODULE_DEVICE_TABLE(usb, device_table); + +/* -- device connect -- */ +static int sd_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), + THIS_MODULE); +} + +static struct usb_driver sd_driver = { + .name = MODULE_NAME, + .id_table = device_table, + .probe = sd_probe, + .disconnect = gspca_disconnect, +#ifdef CONFIG_PM + .suspend = gspca_suspend, + .resume = gspca_resume, +#endif +}; + +/* -- module insert / remove -- */ +static int __init sd_mod_init(void) +{ + int ret; + + ret = usb_register(&sd_driver); + if (ret < 0) + return ret; + return 0; +} +static void __exit sd_mod_exit(void) +{ + usb_deregister(&sd_driver); +} + +module_init(sd_mod_init); +module_exit(sd_mod_exit); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 2965906a02c9..6bfaa767a817 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -401,6 +401,7 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ #define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */ +#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */ #define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */ #define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */ #define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */ -- cgit From 6c06108be53ca5e94d8b0e93883d534dd9079646 Mon Sep 17 00:00:00 2001 From: Dan Carpenter <dan.carpenter@oracle.com> Date: Thu, 5 Jan 2012 02:27:57 -0300 Subject: [media] V4L/DVB: v4l2-ioctl: integer overflow in video_usercopy() If ctrls->count is too high the multiplication could overflow and array_size would be lower than expected. Mauro and Hans Verkuil suggested that we cap it at 1024. That comes from the maximum number of controls with lots of room for expantion. $ grep V4L2_CID include/linux/videodev2.h | wc -l 211 Cc: stable <stable@vger.kernel.org> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/v4l2-ioctl.c | 4 ++++ include/linux/videodev2.h | 1 + 2 files changed, 5 insertions(+) (limited to 'include/linux') diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index e1da8fc9dd2f..639abeee3392 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -2226,6 +2226,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, struct v4l2_ext_controls *ctrls = parg; if (ctrls->count != 0) { + if (ctrls->count > V4L2_CID_MAX_CTRLS) { + ret = -EINVAL; + break; + } *user_ptr = (void __user *)ctrls->controls; *kernel_ptr = (void *)&ctrls->controls; *array_size = sizeof(struct v4l2_ext_control) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 6bfaa767a817..b2e1331ca76b 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1132,6 +1132,7 @@ struct v4l2_querymenu { #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 /* User-class control IDs defined by V4L2 */ +#define V4L2_CID_MAX_CTRLS 1024 #define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) #define V4L2_CID_USER_BASE V4L2_CID_BASE /* IDs reserved for driver specific controls */ -- cgit From 0e8caaceff160ad821c83d798fc03812cb810560 Mon Sep 17 00:00:00 2001 From: Tomasz Stanislawski <t.stanislaws@samsung.com> Date: Wed, 10 Aug 2011 10:37:47 -0300 Subject: [media] v4l: add support for selection api This patch introduces new api for a precise control of cropping and composing features for video devices. The new ioctls are VIDIOC_S_SELECTION and VIDIOC_G_SELECTION. Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> --- drivers/media/video/v4l2-compat-ioctl32.c | 2 ++ drivers/media/video/v4l2-ioctl.c | 34 +++++++++++++++++++++++ include/linux/videodev2.h | 46 +++++++++++++++++++++++++++++++ include/media/v4l2-ioctl.h | 4 +++ 4 files changed, 86 insertions(+) (limited to 'include/linux') diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index c68531b88279..af4419e6c658 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c @@ -985,6 +985,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_CROPCAP: case VIDIOC_G_CROP: case VIDIOC_S_CROP: + case VIDIOC_G_SELECTION: + case VIDIOC_S_SELECTION: case VIDIOC_G_JPEGCOMP: case VIDIOC_S_JPEGCOMP: case VIDIOC_QUERYSTD: diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 639abeee3392..072cfc1a166f 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -238,6 +238,8 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", + [_IOC_NR(VIDIOC_G_SELECTION)] = "VIDIOC_G_SELECTION", + [_IOC_NR(VIDIOC_S_SELECTION)] = "VIDIOC_S_SELECTION", [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", @@ -1571,6 +1573,38 @@ static long __video_do_ioctl(struct file *file, ret = ops->vidioc_s_crop(file, fh, p); break; } + case VIDIOC_G_SELECTION: + { + struct v4l2_selection *p = arg; + + if (!ops->vidioc_g_selection) + break; + + dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); + + ret = ops->vidioc_g_selection(file, fh, p); + if (!ret) + dbgrect(vfd, "", &p->r); + break; + } + case VIDIOC_S_SELECTION: + { + struct v4l2_selection *p = arg; + + if (!ops->vidioc_s_selection) + break; + + if (ret_prio) { + ret = ret_prio; + break; + } + + dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); + dbgrect(vfd, "", &p->r); + + ret = ops->vidioc_s_selection(file, fh, p); + break; + } case VIDIOC_CROPCAP: { struct v4l2_cropcap *p = arg; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index b2e1331ca76b..012a29604522 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -743,6 +743,48 @@ struct v4l2_crop { struct v4l2_rect c; }; +/* Hints for adjustments of selection rectangle */ +#define V4L2_SEL_FLAG_GE 0x00000001 +#define V4L2_SEL_FLAG_LE 0x00000002 + +/* Selection targets */ + +/* current cropping area */ +#define V4L2_SEL_TGT_CROP_ACTIVE 0 +/* default cropping area */ +#define V4L2_SEL_TGT_CROP_DEFAULT 1 +/* cropping bounds */ +#define V4L2_SEL_TGT_CROP_BOUNDS 2 +/* current composing area */ +#define V4L2_SEL_TGT_COMPOSE_ACTIVE 256 +/* default composing area */ +#define V4L2_SEL_TGT_COMPOSE_DEFAULT 257 +/* composing bounds */ +#define V4L2_SEL_TGT_COMPOSE_BOUNDS 258 +/* current composing area plus all padding pixels */ +#define V4L2_SEL_TGT_COMPOSE_PADDED 259 + +/** + * struct v4l2_selection - selection info + * @type: buffer type (do not use *_MPLANE types) + * @target: selection target, used to choose one of possible rectangles + * @flags: constraints flags + * @r: coordinates of selection window + * @reserved: for future use, rounds structure size to 64 bytes, set to zero + * + * Hardware may use multiple helper window to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +struct v4l2_selection { + __u32 type; + __u32 target; + __u32 flags; + struct v4l2_rect r; + __u32 reserved[9]; +}; + + /* * A N A L O G V I D E O S T A N D A R D */ @@ -2259,6 +2301,10 @@ struct v4l2_create_buffers { #define VIDIOC_CREATE_BUFS _IOWR('V', 92, struct v4l2_create_buffers) #define VIDIOC_PREPARE_BUF _IOWR('V', 93, struct v4l2_buffer) +/* Experimental selection API */ +#define VIDIOC_G_SELECTION _IOWR('V', 94, struct v4l2_selection) +#define VIDIOC_S_SELECTION _IOWR('V', 95, struct v4l2_selection) + /* Reminder: when adding new ioctls please add support for them to drivers/media/video/v4l2-compat-ioctl32.c as well! */ diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h index 4d1c74ad4c84..3f5d60fc5df6 100644 --- a/include/media/v4l2-ioctl.h +++ b/include/media/v4l2-ioctl.h @@ -196,6 +196,10 @@ struct v4l2_ioctl_ops { struct v4l2_crop *a); int (*vidioc_s_crop) (struct file *file, void *fh, struct v4l2_crop *a); + int (*vidioc_g_selection) (struct file *file, void *fh, + struct v4l2_selection *s); + int (*vidioc_s_selection) (struct file *file, void *fh, + struct v4l2_selection *s); /* Compression ioctls */ int (*vidioc_g_jpegcomp) (struct file *file, void *fh, struct v4l2_jpegcompression *a); -- cgit