</note>
<para>
- The Image Source control class is intended for low-level control of
+ The Image Process control class is intended for low-level control of
image processing functions. Unlike
<constant>V4L2_CID_IMAGE_SOURCE_CLASS</constant>, the controls in
this class affect processing the image, and do not control capturing
</para>
<table pgwide="1" frame="none" id="image-process-control-id">
- <title>Image Source Control IDs</title>
+ <title>Image Process Control IDs</title>
<tgroup cols="4">
<colspec colname="c1" colwidth="1*" />
<para>To open a media device applications call <function>open()</function>
with the desired device name. The function has no side effects; the device
configuration remain unchanged.</para>
- <para>When the device is opened in read-only mode, attemps to modify its
+ <para>When the device is opened in read-only mode, attempts to modify its
configuration will result in an error, and <varname>errno</varname> will be
set to <errorcode>EBADF</errorcode>.</para>
</refsect1>
<para>If blocks have to be retrieved from the sink, then this call will block until they
have been read.</para>
+ <para>If <structfield>start_block</structfield> and <structfield>blocks</structfield> are
+ both set to 0 when <constant>VIDIOC_G_EDID</constant> is called, then the driver will
+ set <structfield>blocks</structfield> to the total number of available EDID blocks
+ and it will return 0 without copying any data. This is an easy way to discover how many
+ EDID blocks there are. Note that if there are no EDID blocks available at all, then
+ the driver will set <structfield>blocks</structfield> to 0 and it returns 0.</para>
+
<para>To set the EDID blocks of a receiver the application has to fill in the <structfield>pad</structfield>,
<structfield>blocks</structfield> and <structfield>edid</structfield> fields and set
<structfield>start_block</structfield> to 0. It is not possible to set part of an EDID,
--- /dev/null
+* Analog Devices ADP1653 flash LED driver
+
+Required Properties:
+
+ - compatible: Must contain "adi,adp1653"
+
+ - reg: I2C slave address
+
+ - enable-gpios: Specifier of the GPIO connected to EN pin
+
+There are two LED outputs available - flash and indicator. One LED is
+represented by one child node, nodes need to be named "flash" and "indicator".
+
+Required properties of the LED child node:
+- max-microamp : see Documentation/devicetree/bindings/leds/common.txt
+
+Required properties of the flash LED child node:
+
+- flash-max-microamp : see Documentation/devicetree/bindings/leds/common.txt
+- flash-timeout-us : see Documentation/devicetree/bindings/leds/common.txt
+
+Example:
+
+ adp1653: led-controller@30 {
+ compatible = "adi,adp1653";
+ reg = <0x30>;
+ enable-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>; /* 88 */
+
+ flash {
+ flash-timeout-us = <500000>;
+ flash-max-microamp = <320000>;
+ max-microamp = <50000>;
+ };
+ indicator {
+ max-microamp = <17500>;
+ };
+ };
if (f->index != 0)
return -EINVAL;
- strlcpy(f->description, "4:2:2, packed, YUYV", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_YUYV;
- f->flags = 0;
return 0;
}
S: Maintained
F: drivers/net/wan/dscc4.c
+DT3155 MEDIA DRIVER
+M: Hans Verkuil <hverkuil@xs4all.nl>
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+W: http://linuxtv.org
+S: Odd Fixes
+F: drivers/media/pci/dt3155/
+
DVB_USB_AF9015 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
config TOUCHSCREEN_SUR40
tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
- depends on USB
- depends on MEDIA_USB_SUPPORT
+ depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
select INPUT_POLLDEV
select VIDEOBUF2_DMA_SG
help
This API is mostly used by camera interfaces in embedded platforms.
config MEDIA_CONTROLLER_DVB
- bool "Enable Media controller for DVB"
+ bool "Enable Media controller for DVB (EXPERIMENTAL)"
depends on MEDIA_CONTROLLER
---help---
Enable the media controller API support for DVB.
dev->dev.parent = coredev->device;
#if 0
- /* TODO: properly initialize the parameters bellow */
+ /* TODO: properly initialize the parameters below */
dev->input_id.bustype = BUS_USB;
dev->input_id.version = 1;
dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
}
}
+ /* Return an error if can't find bandwidth or the right clock */
+ if (i == ARRAY_SIZE(coeff_lut))
+ return -EINVAL;
+
ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val,
sizeof(coeff_lut[i].val));
}
if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
return ret;
- t = jiffies + 3*HZ;
+ t = jiffies + 3*HZ;
while (time_before(jiffies, t)) {
msleep(10);
if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
return ret;
- t = jiffies + 3*HZ;
+ t = jiffies + 3*HZ;
while (time_before(jiffies, t)) {
msleep(10);
if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
struct cx24116_state *state = fe->demodulator_priv;
int i, ret;
+ /* Validate length */
+ if (d->msg_len > sizeof(d->msg))
+ return -EINVAL;
+
/* Dump DiSEqC message */
if (debug) {
printk(KERN_INFO "cx24116: %s(", __func__);
printk(") toneburst=%d\n", toneburst);
}
- /* Validate length */
- if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
- return -EINVAL;
-
/* DiSEqC message */
for (i = 0; i < d->msg_len; i++)
state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
dev_dbg(&state->priv->i2c->dev, ")\n");
/* Validate length */
- if (d->msg_len > 15)
+ if (d->msg_len > sizeof(d->msg))
return -EINVAL;
/* DiSEqC message */
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static struct i2c_adapter *
+static inline struct i2c_adapter *
cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
u16 wbd_ff_offset;
u8 revision;
- enum frontend_tune_state tune_state;
- u32 current_rf;
+ enum frontend_tune_state tune_state;
+ u32 current_rf;
- /* for the captrim binary search */
+ /* for the captrim binary search */
s8 step;
u16 adc_diff;
const struct dib0070_tuning *current_tune_table_index;
const struct dib0070_lna_match *lna_match;
- u8 wbd_gain_current;
+ u8 wbd_gain_current;
u16 wbd_offset_3_3[2];
/* for the I2C transfer */
} while (0)
static int dib0070_set_bandwidth(struct dvb_frontend *fe)
-{
- struct dib0070_state *state = fe->tuner_priv;
- u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
-
- if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
- tmp |= (0 << 14);
- else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
- tmp |= (1 << 14);
- else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
- tmp |= (2 << 14);
- else
- tmp |= (3 << 14);
-
- dib0070_write_reg(state, 0x02, tmp);
-
- /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
- if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
- u16 value = dib0070_read_reg(state, 0x17);
-
- dib0070_write_reg(state, 0x17, value & 0xfffc);
- tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
- dib0070_write_reg(state, 0x01, tmp | (60 << 9));
-
- dib0070_write_reg(state, 0x17, value);
- }
+ {
+ struct dib0070_state *state = fe->tuner_priv;
+ u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
+
+ if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
+ tmp |= (0 << 14);
+ else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
+ tmp |= (1 << 14);
+ else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
+ tmp |= (2 << 14);
+ else
+ tmp |= (3 << 14);
+
+ dib0070_write_reg(state, 0x02, tmp);
+
+ /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
+ if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
+ u16 value = dib0070_read_reg(state, 0x17);
+
+ dib0070_write_reg(state, 0x17, value & 0xfffc);
+ tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
+ dib0070_write_reg(state, 0x01, tmp | (60 << 9));
+
+ dib0070_write_reg(state, 0x17, value);
+ }
return 0;
}
int ret = 0;
if (*tune_state == CT_TUNER_STEP_0) {
-
dib0070_write_reg(state, 0x0f, 0xed10);
dib0070_write_reg(state, 0x17, 0x0034);
state->adc_diff = 3000;
ret = 20;
- *tune_state = CT_TUNER_STEP_1;
+ *tune_state = CT_TUNER_STEP_1;
} else if (*tune_state == CT_TUNER_STEP_1) {
state->step /= 2;
dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
state->adc_diff = adc;
state->fcaptrim = state->captrim;
-
-
-
}
state->captrim += (step_sign * state->step);
static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
{
struct dib0070_state *state = fe->tuner_priv;
- u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+ u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+
dprintk("CTRL_LO5: 0x%x", lo5);
return dib0070_write_reg(state, 0x15, lo5);
}
dib0070_write_reg(state, 0x1a, 0x0000);
} else {
dib0070_write_reg(state, 0x1b, 0x4112);
- if (state->cfg->vga_filter != 0) {
- dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
- dprintk("vga filter register is set to %x", state->cfg->vga_filter);
- } else
- dib0070_write_reg(state, 0x1a, 0x0009);
+ if (state->cfg->vga_filter != 0) {
+ dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
+ dprintk("vga filter register is set to %x", state->cfg->vga_filter);
+ } else
+ dib0070_write_reg(state, 0x1a, 0x0009);
}
}
EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
struct dib0070_tuning {
- u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
- u8 switch_trim;
- u8 vco_band;
- u8 hfdiv;
- u8 vco_multi;
- u8 presc;
- u8 wbdmux;
- u16 tuner_enable;
+ u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+ u8 switch_trim;
+ u8 vco_band;
+ u8 hfdiv;
+ u8 vco_multi;
+ u8 presc;
+ u8 wbdmux;
+ u16 tuner_enable;
};
struct dib0070_lna_match {
- u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
- u8 lna_band;
+ u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+ u8 lna_band;
};
static const struct dib0070_tuning dib0070s_tuning_table[] = {
- { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
- { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
- { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
- { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
- { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
- { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
- { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
+ { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
+ { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
+ { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
+ { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
+ { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+ { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+ { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
};
static const struct dib0070_tuning dib0070_tuning_table[] = {
- { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
- { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
- { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
- { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
- { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
- { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
- { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
- { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
+ { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
+ { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
+ { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
+ { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
+ { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
+ { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
+ { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
+ { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
};
static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
- { 180000, 0 }, /* VHF */
- { 188000, 1 },
- { 196400, 2 },
- { 250000, 3 },
- { 550000, 0 }, /* UHF */
- { 590000, 1 },
- { 666000, 3 },
- { 864000, 5 },
- { 1500000, 0 }, /* LBAND or everything higher than UHF */
- { 1600000, 1 },
- { 2000000, 3 },
- { 0xffffffff, 7 },
+ { 180000, 0 }, /* VHF */
+ { 188000, 1 },
+ { 196400, 2 },
+ { 250000, 3 },
+ { 550000, 0 }, /* UHF */
+ { 590000, 1 },
+ { 666000, 3 },
+ { 864000, 5 },
+ { 1500000, 0 }, /* LBAND or everything higher than UHF */
+ { 1600000, 1 },
+ { 2000000, 3 },
+ { 0xffffffff, 7 },
};
static const struct dib0070_lna_match dib0070_lna[] = {
- { 180000, 0 }, /* VHF */
- { 188000, 1 },
- { 196400, 2 },
- { 250000, 3 },
- { 550000, 2 }, /* UHF */
- { 650000, 3 },
- { 750000, 5 },
- { 850000, 6 },
- { 864000, 7 },
- { 1500000, 0 }, /* LBAND or everything higher than UHF */
- { 1600000, 1 },
- { 2000000, 3 },
- { 0xffffffff, 7 },
+ { 180000, 0 }, /* VHF */
+ { 188000, 1 },
+ { 196400, 2 },
+ { 250000, 3 },
+ { 550000, 2 }, /* UHF */
+ { 650000, 3 },
+ { 750000, 5 },
+ { 850000, 6 },
+ { 864000, 7 },
+ { 1500000, 0 }, /* LBAND or everything higher than UHF */
+ { 1600000, 1 },
+ { 2000000, 3 },
+ { 0xffffffff, 7 },
};
#define LPF 100
static int dib0070_tune_digital(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
+ struct dib0070_state *state = fe->tuner_priv;
- const struct dib0070_tuning *tune;
- const struct dib0070_lna_match *lna_match;
+ const struct dib0070_tuning *tune;
+ const struct dib0070_lna_match *lna_match;
- enum frontend_tune_state *tune_state = &state->tune_state;
- int ret = 10; /* 1ms is the default delay most of the time */
+ enum frontend_tune_state *tune_state = &state->tune_state;
+ int ret = 10; /* 1ms is the default delay most of the time */
- u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
- u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
+ u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
+ u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
#ifdef CONFIG_SYS_ISDBT
- if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
- if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
- && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
- || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
- && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
- || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
- && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
- freq += 850;
+ if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
+ if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
+ && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+ || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+ && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
+ || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+ && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
+ freq += 850;
#endif
- if (state->current_rf != freq) {
-
- switch (state->revision) {
- case DIB0070S_P1A:
- tune = dib0070s_tuning_table;
- lna_match = dib0070_lna;
- break;
- default:
- tune = dib0070_tuning_table;
- if (state->cfg->flip_chip)
- lna_match = dib0070_lna_flip_chip;
- else
- lna_match = dib0070_lna;
- break;
- }
- while (freq > tune->max_freq) /* find the right one */
- tune++;
- while (freq > lna_match->max_freq) /* find the right one */
- lna_match++;
-
- state->current_tune_table_index = tune;
- state->lna_match = lna_match;
- }
-
- if (*tune_state == CT_TUNER_START) {
- dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
if (state->current_rf != freq) {
- u8 REFDIV;
- u32 FBDiv, Rest, FREF, VCOF_kHz;
- u8 Den;
-
- state->current_rf = freq;
- state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
-
-
- dib0070_write_reg(state, 0x17, 0x30);
-
-
- VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
-
- switch (band) {
- case BAND_VHF:
- REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
- break;
- case BAND_FM:
- REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
- break;
- default:
- REFDIV = (u8) (state->cfg->clock_khz / 10000);
- break;
- }
- FREF = state->cfg->clock_khz / REFDIV;
-
-
switch (state->revision) {
case DIB0070S_P1A:
- FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
- Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
- break;
-
- case DIB0070_P1G:
- case DIB0070_P1F:
+ tune = dib0070s_tuning_table;
+ lna_match = dib0070_lna;
+ break;
default:
- FBDiv = (freq / (FREF / 2));
- Rest = 2 * freq - FBDiv * FREF;
- break;
- }
-
- if (Rest < LPF)
- Rest = 0;
- else if (Rest < 2 * LPF)
- Rest = 2 * LPF;
- else if (Rest > (FREF - LPF)) {
- Rest = 0;
- FBDiv += 1;
- } else if (Rest > (FREF - 2 * LPF))
- Rest = FREF - 2 * LPF;
- Rest = (Rest * 6528) / (FREF / 10);
-
- Den = 1;
- if (Rest > 0) {
- state->lo4 |= (1 << 14) | (1 << 12);
- Den = 255;
+ tune = dib0070_tuning_table;
+ if (state->cfg->flip_chip)
+ lna_match = dib0070_lna_flip_chip;
+ else
+ lna_match = dib0070_lna;
+ break;
}
+ while (freq > tune->max_freq) /* find the right one */
+ tune++;
+ while (freq > lna_match->max_freq) /* find the right one */
+ lna_match++;
+ state->current_tune_table_index = tune;
+ state->lna_match = lna_match;
+ }
- dib0070_write_reg(state, 0x11, (u16)FBDiv);
- dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
- dib0070_write_reg(state, 0x13, (u16) Rest);
-
- if (state->revision == DIB0070S_P1A) {
-
- if (band == BAND_SBAND) {
- dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
- dib0070_write_reg(state, 0x1d, 0xFFFF);
- } else
- dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
+ if (*tune_state == CT_TUNER_START) {
+ dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
+ if (state->current_rf != freq) {
+ u8 REFDIV;
+ u32 FBDiv, Rest, FREF, VCOF_kHz;
+ u8 Den;
+
+ state->current_rf = freq;
+ state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
+
+
+ dib0070_write_reg(state, 0x17, 0x30);
+
+
+ VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
+
+ switch (band) {
+ case BAND_VHF:
+ REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
+ break;
+ case BAND_FM:
+ REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
+ break;
+ default:
+ REFDIV = (u8) (state->cfg->clock_khz / 10000);
+ break;
+ }
+ FREF = state->cfg->clock_khz / REFDIV;
+
+
+
+ switch (state->revision) {
+ case DIB0070S_P1A:
+ FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
+ Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
+ break;
+
+ case DIB0070_P1G:
+ case DIB0070_P1F:
+ default:
+ FBDiv = (freq / (FREF / 2));
+ Rest = 2 * freq - FBDiv * FREF;
+ break;
+ }
+
+ if (Rest < LPF)
+ Rest = 0;
+ else if (Rest < 2 * LPF)
+ Rest = 2 * LPF;
+ else if (Rest > (FREF - LPF)) {
+ Rest = 0;
+ FBDiv += 1;
+ } else if (Rest > (FREF - 2 * LPF))
+ Rest = FREF - 2 * LPF;
+ Rest = (Rest * 6528) / (FREF / 10);
+
+ Den = 1;
+ if (Rest > 0) {
+ state->lo4 |= (1 << 14) | (1 << 12);
+ Den = 255;
+ }
+
+
+ dib0070_write_reg(state, 0x11, (u16)FBDiv);
+ dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
+ dib0070_write_reg(state, 0x13, (u16) Rest);
+
+ if (state->revision == DIB0070S_P1A) {
+
+ if (band == BAND_SBAND) {
+ dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+ dib0070_write_reg(state, 0x1d, 0xFFFF);
+ } else
+ dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
+ }
+
+ dib0070_write_reg(state, 0x20,
+ 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
+
+ dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
+ dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
+ dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
+ dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
+ dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
+ dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
+
+ *tune_state = CT_TUNER_STEP_0;
+ } else { /* we are already tuned to this frequency - the configuration is correct */
+ ret = 50; /* wakeup time */
+ *tune_state = CT_TUNER_STEP_5;
}
+ } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
- dib0070_write_reg(state, 0x20,
- 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
-
- dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
- dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
- dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
- dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
- dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
- dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
-
- *tune_state = CT_TUNER_STEP_0;
- } else { /* we are already tuned to this frequency - the configuration is correct */
- ret = 50; /* wakeup time */
- *tune_state = CT_TUNER_STEP_5;
- }
- } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
-
- ret = dib0070_captrim(state, tune_state);
+ ret = dib0070_captrim(state, tune_state);
- } else if (*tune_state == CT_TUNER_STEP_4) {
- const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
- if (tmp != NULL) {
- while (freq/1000 > tmp->freq) /* find the right one */
- tmp++;
- dib0070_write_reg(state, 0x0f,
- (0 << 15) | (1 << 14) | (3 << 12)
- | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
- | (state->current_tune_table_index->wbdmux << 0));
- state->wbd_gain_current = tmp->wbd_gain_val;
- } else {
+ } else if (*tune_state == CT_TUNER_STEP_4) {
+ const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+ if (tmp != NULL) {
+ while (freq/1000 > tmp->freq) /* find the right one */
+ tmp++;
dib0070_write_reg(state, 0x0f,
- (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
- wbdmux << 0));
- state->wbd_gain_current = 6;
- }
+ (0 << 15) | (1 << 14) | (3 << 12)
+ | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
+ | (state->current_tune_table_index->wbdmux << 0));
+ state->wbd_gain_current = tmp->wbd_gain_val;
+ } else {
+ dib0070_write_reg(state, 0x0f,
+ (0 << 15) | (1 << 14) | (3 << 12)
+ | (6 << 9) | (0 << 8) | (1 << 7)
+ | (state->current_tune_table_index->wbdmux << 0));
+ state->wbd_gain_current = 6;
+ }
- dib0070_write_reg(state, 0x06, 0x3fff);
+ dib0070_write_reg(state, 0x06, 0x3fff);
dib0070_write_reg(state, 0x07,
(state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
- dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
- dib0070_write_reg(state, 0x0d, 0x0d80);
+ dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
+ dib0070_write_reg(state, 0x0d, 0x0d80);
- dib0070_write_reg(state, 0x18, 0x07ff);
- dib0070_write_reg(state, 0x17, 0x0033);
+ dib0070_write_reg(state, 0x18, 0x07ff);
+ dib0070_write_reg(state, 0x17, 0x0033);
- *tune_state = CT_TUNER_STEP_5;
- } else if (*tune_state == CT_TUNER_STEP_5) {
- dib0070_set_bandwidth(fe);
- *tune_state = CT_TUNER_STOP;
- } else {
- ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
- }
- return ret;
+ *tune_state = CT_TUNER_STEP_5;
+ } else if (*tune_state == CT_TUNER_STEP_5) {
+ dib0070_set_bandwidth(fe);
+ *tune_state = CT_TUNER_STOP;
+ } else {
+ ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
+ }
+ return ret;
}
static int dib0070_tune(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
- uint32_t ret;
+ struct dib0070_state *state = fe->tuner_priv;
+ uint32_t ret;
- state->tune_state = CT_TUNER_START;
+ state->tune_state = CT_TUNER_START;
- do {
- ret = dib0070_tune_digital(fe);
- if (ret != FE_CALLBACK_TIME_NEVER)
- msleep(ret/10);
- else
- break;
- } while (state->tune_state != CT_TUNER_STOP);
+ do {
+ ret = dib0070_tune_digital(fe);
+ if (ret != FE_CALLBACK_TIME_NEVER)
+ msleep(ret/10);
+ else
+ break;
+ } while (state->tune_state != CT_TUNER_STOP);
- return 0;
+ return 0;
}
static int dib0070_wakeup(struct dvb_frontend *fe)
static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
{
- u16 tuner_en = dib0070_read_reg(state, 0x20);
- u16 offset;
-
- dib0070_write_reg(state, 0x18, 0x07ff);
- dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
- dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
- msleep(9);
- offset = dib0070_read_reg(state, 0x19);
- dib0070_write_reg(state, 0x20, tuner_en);
- return offset;
+ u16 tuner_en = dib0070_read_reg(state, 0x20);
+ u16 offset;
+
+ dib0070_write_reg(state, 0x18, 0x07ff);
+ dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
+ dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
+ msleep(9);
+ offset = dib0070_read_reg(state, 0x19);
+ dib0070_write_reg(state, 0x20, tuner_en);
+ return offset;
}
static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
{
- u8 gain;
- for (gain = 6; gain < 8; gain++) {
- state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
- dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
- }
+ u8 gain;
+ for (gain = 6; gain < 8; gain++) {
+ state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
+ dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
+ }
}
u16 dib0070_wbd_offset(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
- const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
- u32 freq = fe->dtv_property_cache.frequency/1000;
-
- if (tmp != NULL) {
- while (freq/1000 > tmp->freq) /* find the right one */
- tmp++;
- state->wbd_gain_current = tmp->wbd_gain_val;
+ struct dib0070_state *state = fe->tuner_priv;
+ const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+ u32 freq = fe->dtv_property_cache.frequency/1000;
+
+ if (tmp != NULL) {
+ while (freq/1000 > tmp->freq) /* find the right one */
+ tmp++;
+ state->wbd_gain_current = tmp->wbd_gain_val;
} else
- state->wbd_gain_current = 6;
+ state->wbd_gain_current = 6;
- return state->wbd_offset_3_3[state->wbd_gain_current - 6];
+ return state->wbd_offset_3_3[state->wbd_gain_current - 6];
}
EXPORT_SYMBOL(dib0070_wbd_offset);
#define pgm_read_word(w) (*w)
static int dib0070_reset(struct dvb_frontend *fe)
{
- struct dib0070_state *state = fe->tuner_priv;
+ struct dib0070_state *state = fe->tuner_priv;
u16 l, r, *n;
HARD_RESET(state);
#else
#warning forcing SBAND
#endif
- state->revision = DIB0070S_P1A;
+ state->revision = DIB0070S_P1A;
/* P1F or not */
dprintk("Revision: %x", state->revision);
dib0070_write_reg(state, 0x02, r | (1 << 5));
}
- if (state->revision == DIB0070S_P1A)
- dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
- else
- dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
+ if (state->revision == DIB0070S_P1A)
+ dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+ else
+ dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
+ state->cfg->enable_third_order_filter);
dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
- dib0070_wbd_offset_calibration(state);
+ dib0070_wbd_offset_calibration(state);
- return 0;
+ return 0;
}
static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
- struct dib0070_state *state = fe->tuner_priv;
+ struct dib0070_state *state = fe->tuner_priv;
- *frequency = 1000 * state->current_rf;
- return 0;
+ *frequency = 1000 * state->current_rf;
+ return 0;
}
static int dib0070_release(struct dvb_frontend *fe)
static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
{
u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
- if (state->cfg->pwm3_inversion) {
+ if (state->cfg->pwm3_inversion) {
reg_51 = (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
reg_52 |= (1 << 2);
} else {
dib3000mc_write_word(state, 51, reg_51);
dib3000mc_write_word(state, 52, reg_52);
- if (state->cfg->use_pwm3)
+ if (state->cfg->use_pwm3)
dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
else
dib3000mc_write_word(state, 245, 0);
- dib3000mc_write_word(state, 1040, 0x3);
+ dib3000mc_write_word(state, 1040, 0x3);
return 0;
}
dib3000mc_write_word(state, 1032, 0xFFFF);
dib3000mc_write_word(state, 1033, 0xFFF0);
- return 0;
+ return 0;
}
static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
dib3000mc_set_bandwidth(state, bw);
dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
-// if (boost)
-// dib3000mc_write_word(state, 100, (11 << 6) + 6);
-// else
+#if 1
+ dib3000mc_write_word(state, 100, (16 << 6) + 9);
+#else
+ if (boost)
+ dib3000mc_write_word(state, 100, (11 << 6) + 6);
+ else
dib3000mc_write_word(state, 100, (16 << 6) + 9);
+#endif
dib3000mc_write_word(state, 1027, 0x0800);
dib3000mc_write_word(state, 1027, 0x0000);
#if IS_REACHABLE(CONFIG_DVB_DIB8000)
void *dib8000_attach(struct dib8000_ops *ops);
#else
-static inline int dib8000_attach(struct dib8000_ops *ops)
+static inline void *dib8000_attach(struct dib8000_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
/**
* \def DRXJ_DEF_I2C_ADDR
-* \brief Default I2C addres of a demodulator instance.
+* \brief Default I2C address of a demodulator instance.
*/
#define DRXJ_DEF_I2C_ADDR (0x52)
* MICROCODE RELATED DEFINES
*/
-/* Magic word for checking correct Endianess of microcode data */
+/* Magic word for checking correct Endianness of microcode data */
#define DRX_UCODE_MAGIC_WORD ((((u16)'H')<<8)+((u16)'L'))
/* CRC flag in ucode header, flags field. */
static clockrate is selected */
DRX_MPEG_STR_WIDTH_1 /* MPEG Start width in clock cycles */
},
- /* Initilisations below can be ommited, they require no user input and
+ /* Initilisations below can be omitted, they require no user input and
are initialy 0, NULL or false. The compiler will initialize them to these
- values when ommited. */
+ values when omitted. */
false, /* is_opened */
/* SCAN */
Now x has binary point between bit[scale] and bit[scale-1]
and 1.0 <= x < 2.0 */
- /* correction for divison: log(x) = log(x/y)+log(y) */
+ /* correction for division: log(x) = log(x/y)+log(y) */
y = k * ((((u32) 1) << scale) * 200);
/* remove integer part */
sequense will be visible: (1) write address {i2c addr,
4 bytes chip address} (2) write data {i2c addr, 4 bytes data }
(3) write address (4) write data etc...
- Addres must be rewriten because HI is reset after data transport and
+ Address must be rewriten because HI is reset after data transport and
expects an address.
*/
todo = (block_size < datasize ? block_size : datasize);
} /* ext_attr->standard */
}
- if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> clear ipr_mode[0] */
+ if (cfg_data->enable_parallel == true) { /* MPEG data output is parallel -> clear ipr_mode[0] */
fec_oc_reg_ipr_mode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
} else { /* MPEG data output is serial -> set ipr_mode[0] */
fec_oc_reg_ipr_mode |= FEC_OC_IPR_MODE_SERIAL__M;
pr_err("error %d\n", rc);
goto rw_error;
}
- if (cfg_data->enable_parallel == true) { /* MPEG data output is paralel -> set MD1 to MD7 to output mode */
+ if (cfg_data->enable_parallel == true) { /* MPEG data output is parallel -> set MD1 to MD7 to output mode */
sio_pdr_md_cfg =
MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH <<
SIO_PDR_MD0_CFG_DRIVE__B | 0x03 <<
}
if (count == 1) {
- /* Try sampling on a diffrent edge */
+ /* Try sampling on a different edge */
u16 clk_neg = 0;
rc = drxj_dap_read_reg16(dev_addr, IQM_AF_CLKNEG__A, &clk_neg, 0);
enum drx_modulation constellation, u32 symbol_rate)
{
struct i2c_device_addr *dev_addr = NULL; /* device address for I2C writes */
- struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specif data */
+ struct drxj_data *ext_attr = NULL; /* Global data container for DRXJ specific data */
int rc;
u32 fec_bits_desired = 0; /* BER accounting period */
u16 fec_rs_plen = 0; /* defines RS BER measurement period */
u32 timeout_ofs = 0;
u16 data = 0;
- /* external attributes for storing aquired channel constellation */
+ /* external attributes for storing acquired channel constellation */
*lock_status = DRX_NOT_LOCKED;
start_time = jiffies_to_msecs(jiffies);
lck_state = NO_LOCK;
u32 d_locked_time = 0;
u32 timeout_ofs = DRXJ_QAM_DEMOD_LOCK_EXT_WAITTIME;
- /* external attributes for storing aquired channel constellation */
+ /* external attributes for storing acquired channel constellation */
*lock_status = DRX_NOT_LOCKED;
start_time = jiffies_to_msecs(jiffies);
lck_state = NO_LOCK;
enum drx_lock_status lock_status = DRX_NOT_LOCKED;
bool auto_flag = false;
- /* external attributes for storing aquired channel constellation */
+ /* external attributes for storing acquired channel constellation */
ext_attr = (struct drxj_data *) demod->my_ext_attr;
/* set QAM channel constellation */
/**
* \fn int ctrl_get_qam_sig_quality()
-* \brief Retreive QAM signal quality from device.
+* \brief Retrieve QAM signal quality from device.
* \param devmod Pointer to demodulator instance.
* \param sig_quality Pointer to signal quality data.
* \return int.
/* ----------------------------------------- */
/* Pre Viterbi Symbol Error Rate Calculation */
/* ----------------------------------------- */
- /* pre viterbi SER is good if it is bellow 0.025 */
+ /* pre viterbi SER is good if it is below 0.025 */
/* get the register value */
/* no of quadrature symbol errors */
/**
* \fn int ctrl_sig_quality()
-* \brief Retreive signal quality form device.
+* \brief Retrieve signal quality form device.
* \param devmod Pointer to demodulator instance.
* \param sig_quality Pointer to signal quality data.
* \return int.
/**
* \fn int ctrl_lock_status()
-* \brief Retreive lock status .
+* \brief Retrieve lock status .
* \param dev_addr Pointer to demodulator device address.
* \param lock_stat Pointer to lock status structure.
* \return int.
return -EIO;
}
- /* define the SCU command paramters and execute the command */
+ /* define the SCU command parameters and execute the command */
cmd_scu.parameter_len = 0;
cmd_scu.result_len = 2;
cmd_scu.parameter = NULL;
}
/* Stamp driver version number in SCU data RAM in BCD code
- Done to enable field application engineers to retreive drxdriver version
+ Done to enable field application engineers to retrieve drxdriver version
via I2C from SCU RAM
*/
driver_version = (VERSION_MAJOR / 100) % 10;
return rc;
}
-/* caller is expeced to check if lna is supported before enabling */
+/* caller is expected to check if lna is supported before enabling */
static int drxj_set_lna_state(struct drx_demod_instance *demod, bool state)
{
struct drxuio_cfg uio_cfg;
static int init_state(struct drxk_state *state)
{
/*
- * FIXME: most (all?) of the values bellow should be moved into
+ * FIXME: most (all?) of the values below should be moved into
* struct drxk_config, as they are probably board-specific
*/
u32 ul_vsb_if_agc_mode = DRXK_AGC_CTRL_AUTO;
lgdt3306a_read_reg(state, regtab[i], ®val1[i]);
if (regval1[i] != regval2[i]) {
lg_debug(" %04X = %02X\n", regtab[i], regval1[i]);
- regval2[i] = regval1[i];
+ regval2[i] = regval1[i];
}
}
debug = sav_debug;
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static struct i2c_adapter *
+static inline struct i2c_adapter *
mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
int result = 0;
dprintk("enter %s\n", __func__);
- if (cmd->msg_len > 8)
+ if (cmd->msg_len > sizeof(cmd->msg))
return -EINVAL;
/* setup for DISEQC */
} else {
switch (p->fec_inner) {
case FEC_1_2:
- vit08 = 0x01; vit09 = 0x10;
+ vit08 = 0x01;
+ vit09 = 0x10;
break;
case FEC_2_3:
- vit08 = 0x02; vit09 = 0x11;
+ vit08 = 0x02;
+ vit09 = 0x11;
break;
case FEC_3_4:
- vit08 = 0x04; vit09 = 0x12;
+ vit08 = 0x04;
+ vit09 = 0x12;
break;
case FEC_5_6:
- vit08 = 0x08; vit09 = 0x13;
+ vit08 = 0x08;
+ vit09 = 0x13;
break;
case FEC_6_7:
- vit08 = 0x10; vit09 = 0x14;
+ vit08 = 0x10;
+ vit09 = 0x14;
break;
case FEC_7_8:
- vit08 = 0x20; vit09 = 0x15;
+ vit08 = 0x20;
+ vit09 = 0x15;
break;
default:
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-static struct i2c_adapter *
+static inline struct i2c_adapter *
s921_get_tuner_i2c_adapter(struct dvb_frontend *fe)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
temp = (unsigned int)srate / 1000;
- temp = temp * 32768;
- temp = temp / 25;
- temp = temp / 125;
- b[0] = (unsigned char)((temp >> 12) & 0xff);
- b[1] = (unsigned char)((temp >> 4) & 0xff);
- b[2] = (unsigned char)((temp << 4) & 0xf0);
- stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
- stv0288_writeregI(state, 0x29, 0); /* SFRM */
- stv0288_writeregI(state, 0x2a, 0); /* SFRL */
-
- stv0288_writeregI(state, 0x28, b[0]);
- stv0288_writeregI(state, 0x29, b[1]);
- stv0288_writeregI(state, 0x2a, b[2]);
- dprintk("stv0288: stv0288_set_symbolrate\n");
+ temp = temp * 32768;
+ temp = temp / 25;
+ temp = temp / 125;
+ b[0] = (unsigned char)((temp >> 12) & 0xff);
+ b[1] = (unsigned char)((temp >> 4) & 0xff);
+ b[2] = (unsigned char)((temp << 4) & 0xf0);
+ stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
+ stv0288_writeregI(state, 0x29, 0); /* SFRM */
+ stv0288_writeregI(state, 0x2a, 0); /* SFRL */
+
+ stv0288_writeregI(state, 0x28, b[0]);
+ stv0288_writeregI(state, 0x29, b[1]);
+ stv0288_writeregI(state, 0x2a, b[2]);
+ dprintk("stv0288: stv0288_set_symbolrate\n");
return 0;
}
{
u64 tmp;
- tmp = stv0297_readreg(state, 0x55);
- tmp |= stv0297_readreg(state, 0x56) << 8;
- tmp |= stv0297_readreg(state, 0x57) << 16;
- tmp |= stv0297_readreg(state, 0x58) << 24;
+ tmp = (u64)(stv0297_readreg(state, 0x55)
+ | (stv0297_readreg(state, 0x56) << 8)
+ | (stv0297_readreg(state, 0x57) << 16)
+ | (stv0297_readreg(state, 0x58) << 24));
tmp *= STV0297_CLOCK_KHZ;
tmp >>= 32;
}
symbcomp = 13 * (coarse_srate / 10);
- coarse_freq = (stv0900_read_reg(intp, CFR2) << 8)
- | stv0900_read_reg(intp, CFR1);
+ coarse_freq = (stv0900_read_reg(intp, CFR2) << 8)
+ | stv0900_read_reg(intp, CFR1);
if (symbcomp < intp->symbol_rate[demod])
coarse_srate = 0;
signal_type = STV0900_NODATA;
no_signal = stv0900_check_signal_presence(intp, demod);
- intp->result[demod].locked = FALSE;
+ intp->result[demod].locked = FALSE;
}
}
}
/*
- * gcc optimizes the code bellow the same way as it would code:
+ * gcc optimizes the code below the same way as it would code:
* "if (qam > 5) return -EINVAL;"
* Yet, the code is clearer, as it shows what QAM standards are
* supported by the driver, and avoids the usage of magic numbers on
}
/*
- * gcc optimizes the code bellow the same way as it would code:
+ * gcc optimizes the code below the same way as it would code:
* "if (qam > 5) return -EINVAL;"
* Yet, the code is clearer, as it shows what QAM standards are
* supported by the driver, and avoids the usage of magic numbers on
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
- return -EIO;
+ return -EIO;
}
// tda setup
return -EINVAL;
/* calculate the updated frequency (note: we convert from Hz->kHz) */
- tmp64 = tda10086_read_byte(state, 0x52);
- tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
+ tmp64 = ((u64)tda10086_read_byte(state, 0x52)
+ | (tda10086_read_byte(state, 0x51) << 8));
if (tmp64 & 0x8000)
tmp64 |= 0xffffffffffff0000ULL;
tmp64 = (tmp64 * (SACLK/1000ULL));
static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
struct zl10353_state *state = fe->demodulator_priv;
- u32 ubl = 0;
+ u32 ubl = 0;
- ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
- zl10353_read_register(state, RS_UBC_0);
+ ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
+ zl10353_read_register(state, RS_UBC_0);
- state->ucblocks += ubl;
- *ucblocks = state->ucblocks;
+ state->ucblocks += ubl;
+ *ucblocks = state->ucblocks;
return 0;
}
* Contributors:
* Sakari Ailus <sakari.ailus@iki.fi>
* Tuukka Toivonen <tuukkat76@gmail.com>
+ * Pavel Machek <pavel@ucw.cz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/gpio/consumer.h>
#include <media/adp1653.h>
#include <media/v4l2-device.h>
{
int ret;
- ret = flash->platform_data->power(&flash->subdev, on);
- if (ret < 0)
- return ret;
+ if (flash->platform_data->power) {
+ ret = flash->platform_data->power(&flash->subdev, on);
+ if (ret < 0)
+ return ret;
+ } else {
+ gpiod_set_value(flash->platform_data->enable_gpio, on);
+ if (on)
+ /* Some delay is apparently required. */
+ udelay(20);
+ }
if (!on)
return 0;
ret = adp1653_init_device(flash);
- if (ret < 0)
+ if (ret >= 0)
+ return ret;
+
+ if (flash->platform_data->power)
flash->platform_data->power(&flash->subdev, 0);
+ else
+ gpiod_set_value(flash->platform_data->enable_gpio, 0);
return ret;
}
#endif /* CONFIG_PM */
+static int adp1653_of_init(struct i2c_client *client,
+ struct adp1653_flash *flash,
+ struct device_node *node)
+{
+ struct adp1653_platform_data *pd;
+ struct device_node *child;
+
+ pd = devm_kzalloc(&client->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+ flash->platform_data = pd;
+
+ child = of_get_child_by_name(node, "flash");
+ if (!child)
+ return -EINVAL;
+
+ if (of_property_read_u32(child, "flash-timeout-us",
+ &pd->max_flash_timeout))
+ goto err;
+
+ if (of_property_read_u32(child, "flash-max-microamp",
+ &pd->max_flash_intensity))
+ goto err;
+
+ pd->max_flash_intensity /= 1000;
+
+ if (of_property_read_u32(child, "led-max-microamp",
+ &pd->max_torch_intensity))
+ goto err;
+
+ pd->max_torch_intensity /= 1000;
+ of_node_put(child);
+
+ child = of_get_child_by_name(node, "indicator");
+ if (!child)
+ return -EINVAL;
+
+ if (of_property_read_u32(child, "led-max-microamp",
+ &pd->max_indicator_intensity))
+ goto err;
+
+ of_node_put(child);
+
+ pd->enable_gpio = devm_gpiod_get(&client->dev, "enable");
+ if (!pd->enable_gpio) {
+ dev_err(&client->dev, "Error getting GPIO\n");
+ return -EINVAL;
+ }
+
+ return 0;
+err:
+ dev_err(&client->dev, "Required property not found\n");
+ of_node_put(child);
+ return -EINVAL;
+}
+
+
static int adp1653_probe(struct i2c_client *client,
const struct i2c_device_id *devid)
{
struct adp1653_flash *flash;
int ret;
- /* we couldn't work without platform data */
- if (client->dev.platform_data == NULL)
- return -ENODEV;
-
flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
if (flash == NULL)
return -ENOMEM;
- flash->platform_data = client->dev.platform_data;
+ if (client->dev.of_node) {
+ ret = adp1653_of_init(client, flash, client->dev.of_node);
+ if (ret)
+ return ret;
+ } else {
+ if (!client->dev.platform_data) {
+ dev_err(&client->dev,
+ "Neither DT not platform data provided\n");
+ return EINVAL;
+ }
+ flash->platform_data = client->dev.platform_data;
+ }
mutex_init(&flash->power_lock);
return 0;
free_and_quit:
+ dev_err(&client->dev, "adp1653: failed to register device\n");
v4l2_ctrl_handler_free(&flash->ctrls);
return ret;
}
};
MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
-static struct dev_pm_ops adp1653_pm_ops = {
+static const struct dev_pm_ops adp1653_pm_ops = {
.suspend = adp1653_suspend,
.resume = adp1653_resume,
};
return 0;
}
-static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int adv7170_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(adv7170_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(adv7170_codes))
return -EINVAL;
- *code = adv7170_codes[index];
+ code->code = adv7170_codes[code->index];
return 0;
}
-static int adv7170_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7170_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7170_read(sd, 0x7);
+ if (format->pad)
+ return -EINVAL;
+
if ((val & 0x40) == (1 << 6))
mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
else
return 0;
}
-static int adv7170_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7170_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7170_read(sd, 0x7);
- int ret;
+ int ret = 0;
+
+ if (format->pad)
+ return -EINVAL;
switch (mf->code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
return -EINVAL;
}
- ret = adv7170_write(sd, 0x7, val);
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ ret = adv7170_write(sd, 0x7, val);
return ret;
}
static const struct v4l2_subdev_video_ops adv7170_video_ops = {
.s_std_output = adv7170_s_std_output,
.s_routing = adv7170_s_routing,
- .s_mbus_fmt = adv7170_s_fmt,
- .g_mbus_fmt = adv7170_g_fmt,
- .enum_mbus_fmt = adv7170_enum_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops adv7170_pad_ops = {
+ .enum_mbus_code = adv7170_enum_mbus_code,
+ .get_fmt = adv7170_get_fmt,
+ .set_fmt = adv7170_set_fmt,
};
static const struct v4l2_subdev_ops adv7170_ops = {
.video = &adv7170_video_ops,
+ .pad = &adv7170_pad_ops,
};
/* ----------------------------------------------------------------------- */
return 0;
}
-static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int adv7175_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(adv7175_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(adv7175_codes))
return -EINVAL;
- *code = adv7175_codes[index];
+ code->code = adv7175_codes[code->index];
return 0;
}
-static int adv7175_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7175_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7175_read(sd, 0x7);
+ if (format->pad)
+ return -EINVAL;
+
if ((val & 0x40) == (1 << 6))
mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
else
return 0;
}
-static int adv7175_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int adv7175_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
u8 val = adv7175_read(sd, 0x7);
- int ret;
+ int ret = 0;
+
+ if (format->pad)
+ return -EINVAL;
switch (mf->code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
return -EINVAL;
}
- ret = adv7175_write(sd, 0x7, val);
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ ret = adv7175_write(sd, 0x7, val);
return ret;
}
static const struct v4l2_subdev_video_ops adv7175_video_ops = {
.s_std_output = adv7175_s_std_output,
.s_routing = adv7175_s_routing,
- .s_mbus_fmt = adv7175_s_fmt,
- .g_mbus_fmt = adv7175_g_fmt,
- .enum_mbus_fmt = adv7175_enum_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops adv7175_pad_ops = {
+ .enum_mbus_code = adv7175_enum_mbus_code,
+ .get_fmt = adv7175_get_fmt,
+ .set_fmt = adv7175_set_fmt,
};
static const struct v4l2_subdev_ops adv7175_ops = {
.core = &adv7175_core_ops,
.video = &adv7175_video_ops,
+ .pad = &adv7175_pad_ops,
};
/* ----------------------------------------------------------------------- */
return 0;
}
-static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int adv7183_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index > 0)
+ if (code->pad || code->index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
return 0;
}
-static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int adv7183_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct adv7183 *decoder = to_adv7183(sd);
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt->width = 720;
fmt->height = 576;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ decoder->fmt = *fmt;
+ else
+ cfg->try_fmt = *fmt;
return 0;
}
-static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int adv7183_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct adv7183 *decoder = to_adv7183(sd);
- adv7183_try_mbus_fmt(sd, fmt);
- decoder->fmt = *fmt;
- return 0;
-}
-
-static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
-{
- struct adv7183 *decoder = to_adv7183(sd);
+ if (format->pad)
+ return -EINVAL;
- *fmt = decoder->fmt;
+ format->format = decoder->fmt;
return 0;
}
.s_routing = adv7183_s_routing,
.querystd = adv7183_querystd,
.g_input_status = adv7183_g_input_status,
- .enum_mbus_fmt = adv7183_enum_mbus_fmt,
- .try_mbus_fmt = adv7183_try_mbus_fmt,
- .s_mbus_fmt = adv7183_s_mbus_fmt,
- .g_mbus_fmt = adv7183_g_mbus_fmt,
.s_stream = adv7183_s_stream,
};
+static const struct v4l2_subdev_pad_ops adv7183_pad_ops = {
+ .enum_mbus_code = adv7183_enum_mbus_code,
+ .get_fmt = adv7183_get_fmt,
+ .set_fmt = adv7183_set_fmt,
+};
+
static const struct v4l2_subdev_ops adv7183_ops = {
.core = &adv7183_core_ops,
.video = &adv7183_video_ops,
+ .pad = &adv7183_pad_ops,
};
static int adv7183_probe(struct i2c_client *client,
struct v4l2_subdev *sd;
struct v4l2_ctrl_handler *hdl;
int ret;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
const unsigned *pin_array;
/* Check if the adapter supports the needed features */
adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs));
adv7183_s_std(sd, decoder->std);
- fmt.width = 720;
- fmt.height = 576;
- adv7183_s_mbus_fmt(sd, &fmt);
+ fmt.format.width = 720;
+ fmt.format.height = 576;
+ adv7183_set_fmt(sd, NULL, &fmt);
/* initialize the hardware to the default control values */
ret = v4l2_ctrl_handler_setup(hdl);
unsigned int num_recommended_settings[2];
unsigned long page_mask;
+
+ /* Masks for timings */
+ unsigned int linewidth_mask;
+ unsigned int field0_height_mask;
+ unsigned int field1_height_mask;
+ unsigned int hfrontporch_mask;
+ unsigned int hsync_mask;
+ unsigned int hbackporch_mask;
+ unsigned int field0_vfrontporch_mask;
+ unsigned int field1_vfrontporch_mask;
+ unsigned int field0_vsync_mask;
+ unsigned int field1_vsync_mask;
+ unsigned int field0_vbackporch_mask;
+ unsigned int field1_vbackporch_mask;
};
/*
if (is_digital_input(sd)) {
timings->type = V4L2_DV_BT_656_1120;
- /* FIXME: All masks are incorrect for ADV7611 */
- bt->width = hdmi_read16(sd, 0x07, 0xfff);
- bt->height = hdmi_read16(sd, 0x09, 0xfff);
+ bt->width = hdmi_read16(sd, 0x07, info->linewidth_mask);
+ bt->height = hdmi_read16(sd, 0x09, info->field0_height_mask);
bt->pixelclock = info->read_hdmi_pixelclock(sd);
- bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff);
- bt->hsync = hdmi_read16(sd, 0x22, 0x3ff);
- bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff);
- bt->vfrontporch = hdmi_read16(sd, 0x2a, 0x1fff) / 2;
- bt->vsync = hdmi_read16(sd, 0x2e, 0x1fff) / 2;
- bt->vbackporch = hdmi_read16(sd, 0x32, 0x1fff) / 2;
+ bt->hfrontporch = hdmi_read16(sd, 0x20, info->hfrontporch_mask);
+ bt->hsync = hdmi_read16(sd, 0x22, info->hsync_mask);
+ bt->hbackporch = hdmi_read16(sd, 0x24, info->hbackporch_mask);
+ bt->vfrontporch = hdmi_read16(sd, 0x2a,
+ info->field0_vfrontporch_mask) / 2;
+ bt->vsync = hdmi_read16(sd, 0x2e, info->field0_vsync_mask) / 2;
+ bt->vbackporch = hdmi_read16(sd, 0x32,
+ info->field0_vbackporch_mask) / 2;
bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
if (bt->interlaced == V4L2_DV_INTERLACED) {
- bt->height += hdmi_read16(sd, 0x0b, 0xfff);
- bt->il_vfrontporch = hdmi_read16(sd, 0x2c, 0x1fff) / 2;
- bt->il_vsync = hdmi_read16(sd, 0x30, 0x1fff) / 2;
- bt->il_vbackporch = hdmi_read16(sd, 0x34, 0x1fff) / 2;
+ bt->height += hdmi_read16(sd, 0x0b,
+ info->field1_height_mask);
+ bt->il_vfrontporch = hdmi_read16(sd, 0x2c,
+ info->field1_vfrontporch_mask) / 2;
+ bt->il_vsync = hdmi_read16(sd, 0x30,
+ info->field1_vsync_mask) / 2;
+ bt->il_vbackporch = hdmi_read16(sd, 0x34,
+ info->field1_vbackporch_mask) / 2;
}
adv76xx_fill_optional_dv_timings_fields(sd, timings);
} else {
BIT(ADV76XX_PAGE_EDID) | BIT(ADV76XX_PAGE_HDMI) |
BIT(ADV76XX_PAGE_TEST) | BIT(ADV76XX_PAGE_CP) |
BIT(ADV7604_PAGE_VDP),
+ .linewidth_mask = 0xfff,
+ .field0_height_mask = 0xfff,
+ .field1_height_mask = 0xfff,
+ .hfrontporch_mask = 0x3ff,
+ .hsync_mask = 0x3ff,
+ .hbackporch_mask = 0x3ff,
+ .field0_vfrontporch_mask = 0x1fff,
+ .field0_vsync_mask = 0x1fff,
+ .field0_vbackporch_mask = 0x1fff,
+ .field1_vfrontporch_mask = 0x1fff,
+ .field1_vsync_mask = 0x1fff,
+ .field1_vbackporch_mask = 0x1fff,
},
[ADV7611] = {
.type = ADV7611,
BIT(ADV76XX_PAGE_INFOFRAME) | BIT(ADV76XX_PAGE_AFE) |
BIT(ADV76XX_PAGE_REP) | BIT(ADV76XX_PAGE_EDID) |
BIT(ADV76XX_PAGE_HDMI) | BIT(ADV76XX_PAGE_CP),
+ .linewidth_mask = 0x1fff,
+ .field0_height_mask = 0x1fff,
+ .field1_height_mask = 0x1fff,
+ .hfrontporch_mask = 0x1fff,
+ .hsync_mask = 0x1fff,
+ .hbackporch_mask = 0x1fff,
+ .field0_vfrontporch_mask = 0x3fff,
+ .field0_vsync_mask = 0x3fff,
+ .field0_vbackporch_mask = 0x3fff,
+ .field1_vfrontporch_mask = 0x3fff,
+ .field1_vsync_mask = 0x3fff,
+ .field1_vbackporch_mask = 0x3fff,
},
};
return 0;
}
-static int adv7842_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int adv7842_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
/* Good enough for now */
- *code = MEDIA_BUS_FMT_FIXED;
+ code->code = MEDIA_BUS_FMT_FIXED;
return 0;
}
-static int adv7842_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int adv7842_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct adv7842_state *state = to_state(sd);
+ if (format->pad)
+ return -EINVAL;
+
fmt->width = state->timings.bt.width;
fmt->height = state->timings.bt.height;
fmt->code = MEDIA_BUS_FMT_FIXED;
.s_dv_timings = adv7842_s_dv_timings,
.g_dv_timings = adv7842_g_dv_timings,
.query_dv_timings = adv7842_query_dv_timings,
- .enum_mbus_fmt = adv7842_enum_mbus_fmt,
- .g_mbus_fmt = adv7842_g_mbus_fmt,
- .try_mbus_fmt = adv7842_g_mbus_fmt,
- .s_mbus_fmt = adv7842_g_mbus_fmt,
};
static const struct v4l2_subdev_pad_ops adv7842_pad_ops = {
.set_edid = adv7842_set_edid,
.enum_dv_timings = adv7842_enum_dv_timings,
.dv_timings_cap = adv7842_dv_timings_cap,
+ .enum_mbus_code = adv7842_enum_mbus_code,
+ .get_fmt = adv7842_fill_fmt,
+ .set_fmt = adv7842_fill_fmt,
};
static const struct v4l2_subdev_ops adv7842_ops = {
}
#endif
-static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ak881x_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ak881x *ak881x = to_ak881x(client);
+ if (format->pad)
+ return -EINVAL;
+
v4l_bound_align_image(&mf->width, 0, 720, 2,
&mf->height, 0, ak881x->lines, 1, 0);
mf->field = V4L2_FIELD_INTERLACED;
return 0;
}
-static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ak881x_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (mf->field != V4L2_FIELD_INTERLACED ||
- mf->code != MEDIA_BUS_FMT_YUYV8_2X8)
+ if (code->pad || code->index)
return -EINVAL;
- return ak881x_try_g_mbus_fmt(sd, mf);
-}
-
-static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
-{
- if (index)
- return -EINVAL;
-
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
return 0;
}
};
static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = {
- .s_mbus_fmt = ak881x_s_mbus_fmt,
- .g_mbus_fmt = ak881x_try_g_mbus_fmt,
- .try_mbus_fmt = ak881x_try_g_mbus_fmt,
.cropcap = ak881x_cropcap,
- .enum_mbus_fmt = ak881x_enum_mbus_fmt,
.s_std_output = ak881x_s_std_output,
.s_stream = ak881x_s_stream,
};
+static const struct v4l2_subdev_pad_ops ak881x_subdev_pad_ops = {
+ .enum_mbus_code = ak881x_enum_mbus_code,
+ .set_fmt = ak881x_fill_fmt,
+ .get_fmt = ak881x_fill_fmt,
+};
+
static struct v4l2_subdev_ops ak881x_subdev_ops = {
.core = &ak881x_subdev_core_ops,
.video = &ak881x_subdev_video_ops,
+ .pad = &ak881x_subdev_pad_ops,
};
static int ak881x_probe(struct i2c_client *client,
not used by any public broadcast network, force
6.5 MHz carrier to be interpreted as System DK,
this avoids DK audio detection instability */
- cx25840_write(client, 0x80b, 0x00);
+ cx25840_write(client, 0x80b, 0x00);
} else if (std & V4L2_STD_SECAM) {
/* Autodetect audio standard and audio system */
cx25840_write(client, 0x808, 0xff);
/* ----------------------------------------------------------------------- */
-static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int cx25840_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->width, fmt->height);
return -ERANGE;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
.s_std = cx25840_s_std,
.g_std = cx25840_g_std,
.s_routing = cx25840_s_video_routing,
- .s_mbus_fmt = cx25840_s_mbus_fmt,
.s_stream = cx25840_s_stream,
.g_input_status = cx25840_g_input_status,
};
.g_sliced_fmt = cx25840_g_sliced_fmt,
};
+static const struct v4l2_subdev_pad_ops cx25840_pad_ops = {
+ .set_fmt = cx25840_set_fmt,
+};
+
static const struct v4l2_subdev_ops cx25840_ops = {
.core = &cx25840_core_ops,
.tuner = &cx25840_tuner_ops,
.audio = &cx25840_audio_ops,
.video = &cx25840_video_ops,
.vbi = &cx25840_vbi_ops,
+ .pad = &cx25840_pad_ops,
.ir = &cx25840_ir_ops,
};
return 0;
}
-static int ml86v7667_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ml86v7667_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index > 0)
+ if (code->pad || code->index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ code->code = MEDIA_BUS_FMT_YUYV8_2X8;
return 0;
}
-static int ml86v7667_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int ml86v7667_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct ml86v7667_priv *priv = to_ml86v7667(sd);
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
.s_std = ml86v7667_s_std,
.querystd = ml86v7667_querystd,
.g_input_status = ml86v7667_g_input_status,
- .enum_mbus_fmt = ml86v7667_enum_mbus_fmt,
- .try_mbus_fmt = ml86v7667_mbus_fmt,
- .g_mbus_fmt = ml86v7667_mbus_fmt,
- .s_mbus_fmt = ml86v7667_mbus_fmt,
.g_mbus_config = ml86v7667_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ml86v7667_subdev_pad_ops = {
+ .enum_mbus_code = ml86v7667_enum_mbus_code,
+ .get_fmt = ml86v7667_fill_fmt,
+ .set_fmt = ml86v7667_fill_fmt,
+};
+
static struct v4l2_subdev_core_ops ml86v7667_subdev_core_ops = {
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = ml86v7667_g_register,
static struct v4l2_subdev_ops ml86v7667_subdev_ops = {
.core = &ml86v7667_subdev_core_ops,
.video = &ml86v7667_subdev_video_ops,
+ .pad = &ml86v7667_subdev_pad_ops,
};
static int ml86v7667_init(struct ml86v7667_priv *priv)
return 0;
}
-static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int mt9v011_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index > 0)
+ if (code->pad || code->index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_SGRBG8_1X8;
+ code->code = MEDIA_BUS_FMT_SGRBG8_1X8;
return 0;
}
-static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int mt9v011_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
- if (fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8)
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+ struct mt9v011 *core = to_mt9v011(sd);
+
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8)
return -EINVAL;
v4l_bound_align_image(&fmt->width, 48, 639, 1,
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ core->width = fmt->width;
+ core->height = fmt->height;
+
+ set_res(sd);
+ } else {
+ cfg->try_fmt = *fmt;
+ }
+
return 0;
}
return 0;
}
-static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
-{
- struct mt9v011 *core = to_mt9v011(sd);
- int rc;
-
- rc = mt9v011_try_mbus_fmt(sd, fmt);
- if (rc < 0)
- return -EINVAL;
-
- core->width = fmt->width;
- core->height = fmt->height;
-
- set_res(sd);
-
- return 0;
-}
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9v011_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
};
static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
- .enum_mbus_fmt = mt9v011_enum_mbus_fmt,
- .try_mbus_fmt = mt9v011_try_mbus_fmt,
- .s_mbus_fmt = mt9v011_s_mbus_fmt,
.g_parm = mt9v011_g_parm,
.s_parm = mt9v011_s_parm,
};
+static const struct v4l2_subdev_pad_ops mt9v011_pad_ops = {
+ .enum_mbus_code = mt9v011_enum_mbus_code,
+ .set_fmt = mt9v011_set_fmt,
+};
+
static const struct v4l2_subdev_ops mt9v011_ops = {
.core = &mt9v011_core_ops,
.video = &mt9v011_video_ops,
+ .pad = &mt9v011_pad_ops,
};
struct v4l2_subdev_format *fmt)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- unsigned int index = ARRAY_SIZE(ov2659_formats);
+ int index = ARRAY_SIZE(ov2659_formats);
struct v4l2_mbus_framefmt *mf = &fmt->format;
const struct ov2659_framesize *size = NULL;
struct ov2659 *ov2659 = to_ov2659(sd);
} ov7670_formats[] = {
{
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
- .colorspace = V4L2_COLORSPACE_JPEG,
+ .colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_yuv422,
.cmatrix = { 128, -128, 0, -34, -94, 128 },
},
}
-static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int ov7670_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= N_OV7670_FMTS)
+ if (code->pad || code->index >= N_OV7670_FMTS)
return -EINVAL;
- *code = ov7670_formats[index].mbus_code;
+ code->code = ov7670_formats[code->index].mbus_code;
return 0;
}
return 0;
}
-static int ov7670_try_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
-{
- return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
-}
-
/*
* Set a format.
*/
-static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int ov7670_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct ov7670_format_struct *ovfmt;
struct ov7670_win_size *wsize;
unsigned char com7;
int ret;
- ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
+ if (format->pad)
+ return -EINVAL;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL);
+ if (ret)
+ return ret;
+ cfg->try_fmt = format->format;
+ return 0;
+ }
+
+ ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize);
if (ret)
return ret;
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_frame_interval_enum *fie)
{
+ struct ov7670_info *info = to_state(sd);
+ unsigned int n_win_sizes = info->devtype->n_win_sizes;
+ int i;
+
if (fie->pad)
return -EINVAL;
if (fie->index >= ARRAY_SIZE(ov7670_frame_rates))
return -EINVAL;
+
+ /*
+ * Check if the width/height is valid.
+ *
+ * If a minimum width/height was requested, filter out the capture
+ * windows that fall outside that.
+ */
+ for (i = 0; i < n_win_sizes; i++) {
+ struct ov7670_win_size *win = &info->devtype->win_sizes[i];
+
+ if (info->min_width && win->width < info->min_width)
+ continue;
+ if (info->min_height && win->height < info->min_height)
+ continue;
+ if (fie->width == win->width && fie->height == win->height)
+ break;
+ }
+ if (i == n_win_sizes)
+ return -EINVAL;
fie->interval.numerator = 1;
fie->interval.denominator = ov7670_frame_rates[fie->index];
return 0;
unsigned char com1, com8, aech, aechh;
ret = ov7670_read(sd, REG_COM1, &com1) +
- ov7670_read(sd, REG_COM8, &com8);
+ ov7670_read(sd, REG_COM8, &com8) +
ov7670_read(sd, REG_AECHH, &aechh);
if (ret)
return ret;
};
static const struct v4l2_subdev_video_ops ov7670_video_ops = {
- .enum_mbus_fmt = ov7670_enum_mbus_fmt,
- .try_mbus_fmt = ov7670_try_mbus_fmt,
- .s_mbus_fmt = ov7670_s_mbus_fmt,
.s_parm = ov7670_s_parm,
.g_parm = ov7670_g_parm,
};
static const struct v4l2_subdev_pad_ops ov7670_pad_ops = {
.enum_frame_interval = ov7670_enum_frame_interval,
.enum_frame_size = ov7670_enum_frame_size,
+ .enum_mbus_code = ov7670_enum_mbus_code,
+ .set_fmt = ov7670_set_fmt,
};
static const struct v4l2_subdev_ops ov7670_ops = {
state->apply_fiv = 1;
state->apply_fmt = 1;
}
- } else if (!on == state->power) {
+ } else if (state->power == !on) {
ret = s5c73m3_set_af_softlanding(state);
if (!ret)
ret = __s5c73m3_power_off(state);
mutex_lock(&state->lock);
- if (!on != state->power)
+ if (state->power != !on)
goto out;
if (on) {
mutex_lock(&s5k6aa->lock);
- if (!on == s5k6aa->power) {
+ if (s5k6aa->power == !on) {
if (on) {
ret = __s5k6aa_power_on(s5k6aa);
if (!ret)
return 0;
}
-static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+static int saa6752hs_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *f = &format->format;
struct saa6752hs_state *h = to_state(sd);
+ if (format->pad)
+ return -EINVAL;
+
if (h->video_format == SAA6752HS_VF_UNKNOWN)
h->video_format = SAA6752HS_VF_D1;
f->width = v4l2_format_table[h->video_format].fmt.pix.width;
return 0;
}
-static int saa6752hs_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+static int saa6752hs_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *f = &format->format;
+ struct saa6752hs_state *h = to_state(sd);
int dist_352, dist_480, dist_720;
+ if (format->pad)
+ return -EINVAL;
+
f->code = MEDIA_BUS_FMT_FIXED;
dist_352 = abs(f->width - 352);
}
f->field = V4L2_FIELD_INTERLACED;
f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- return 0;
-}
-
-static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct saa6752hs_state *h = to_state(sd);
- if (f->code != MEDIA_BUS_FMT_FIXED)
- return -EINVAL;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *f;
+ return 0;
+ }
/*
FIXME: translate and round width/height into EMPRESS
D1 | 720x576 | 720x480
*/
- saa6752hs_try_mbus_fmt(sd, f);
+ if (f->code != MEDIA_BUS_FMT_FIXED)
+ return -EINVAL;
+
if (f->width == 720)
h->video_format = SAA6752HS_VF_D1;
else if (f->width == 480)
static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
.s_std = saa6752hs_s_std,
- .s_mbus_fmt = saa6752hs_s_mbus_fmt,
- .try_mbus_fmt = saa6752hs_try_mbus_fmt,
- .g_mbus_fmt = saa6752hs_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops saa6752hs_pad_ops = {
+ .get_fmt = saa6752hs_get_fmt,
+ .set_fmt = saa6752hs_set_fmt,
};
static const struct v4l2_subdev_ops saa6752hs_ops = {
.core = &saa6752hs_core_ops,
.video = &saa6752hs_video_ops,
+ .pad = &saa6752hs_pad_ops,
};
static int saa6752hs_probe(struct i2c_client *client,
return 0;
}
-static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int saa711x_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
return saa711x_set_size(sd, fmt->width, fmt->height);
}
.s_std = saa711x_s_std,
.s_routing = saa711x_s_routing,
.s_crystal_freq = saa711x_s_crystal_freq,
- .s_mbus_fmt = saa711x_s_mbus_fmt,
.s_stream = saa711x_s_stream,
.querystd = saa711x_querystd,
.g_input_status = saa711x_g_input_status,
.s_raw_fmt = saa711x_s_raw_fmt,
};
+static const struct v4l2_subdev_pad_ops saa711x_pad_ops = {
+ .set_fmt = saa711x_set_fmt,
+};
+
static const struct v4l2_subdev_ops saa711x_ops = {
.core = &saa711x_core_ops,
.tuner = &saa711x_tuner_ops,
.audio = &saa711x_audio_ops,
.video = &saa711x_video_ops,
.vbi = &saa711x_vbi_ops,
+ .pad = &saa711x_pad_ops,
};
#define CHIP_VER_SIZE 16
i2c_transfer(adap, msgs, 2);
if (fw_addr)
- value = (mm2[2] & 0xff) | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
+ value = (mm2[2] << 16) | (mm2[1] << 8) | mm2[0];
else
- value = mm2[0] & 0xff;
+ value = mm2[0];
v4l2_dbg(2, debug, sd, "read: reg 0x%03x=0x%08x\n", reg, value);
return value;
}
#endif
-static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int saa717x_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
int prescale, h_scale, v_scale;
v4l2_dbg(1, debug, sd, "decoder set size\n");
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
/* FIXME need better bounds checking here */
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
/* scaling setting */
/* NTSC and interlace only */
prescale = SAA717X_NTSC_WIDTH / fmt->width;
static const struct v4l2_subdev_video_ops saa717x_video_ops = {
.s_std = saa717x_s_std,
.s_routing = saa717x_s_video_routing,
- .s_mbus_fmt = saa717x_s_mbus_fmt,
.s_stream = saa717x_s_stream,
};
.s_routing = saa717x_s_audio_routing,
};
+static const struct v4l2_subdev_pad_ops saa717x_pad_ops = {
+ .set_fmt = saa717x_set_fmt,
+};
+
static const struct v4l2_subdev_ops saa717x_ops = {
.core = &saa717x_core_ops,
.tuner = &saa717x_tuner_ops,
.audio = &saa717x_audio_ops,
.video = &saa717x_video_ops,
+ .pad = &saa717x_pad_ops,
};
/* ----------------------------------------------------------------------- */
static struct smiapp_platform_data *smiapp_get_pdata(struct device *dev)
{
struct smiapp_platform_data *pdata;
- struct v4l2_of_endpoint bus_cfg;
+ struct v4l2_of_endpoint *bus_cfg;
struct device_node *ep;
- uint32_t asize;
+ int i;
int rval;
if (!dev->of_node)
if (!ep)
return NULL;
+ bus_cfg = v4l2_of_alloc_parse_endpoint(ep);
+ if (IS_ERR(bus_cfg))
+ goto out_err;
+
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
goto out_err;
- v4l2_of_parse_endpoint(ep, &bus_cfg);
-
- switch (bus_cfg.bus_type) {
+ switch (bus_cfg->bus_type) {
case V4L2_MBUS_CSI2:
pdata->csi_signalling_mode = SMIAPP_CSI_SIGNALLING_MODE_CSI2;
break;
goto out_err;
}
- pdata->lanes = bus_cfg.bus.mipi_csi2.num_data_lanes;
+ pdata->lanes = bus_cfg->bus.mipi_csi2.num_data_lanes;
dev_dbg(dev, "lanes %u\n", pdata->lanes);
/* xshutdown GPIO is optional */
dev_dbg(dev, "reset %d, nvm %d, clk %d, csi %d\n", pdata->xshutdown,
pdata->nvm_size, pdata->ext_clk, pdata->csi_signalling_mode);
- rval = of_get_property(ep, "link-frequencies", &asize) ? 0 : -ENOENT;
- if (rval) {
- dev_warn(dev, "can't get link-frequencies array size\n");
+ if (!bus_cfg->nr_of_link_frequencies) {
+ dev_warn(dev, "no link frequencies defined\n");
goto out_err;
}
- pdata->op_sys_clock = devm_kzalloc(dev, asize, GFP_KERNEL);
+ pdata->op_sys_clock = devm_kcalloc(
+ dev, bus_cfg->nr_of_link_frequencies + 1 /* guardian */,
+ sizeof(*pdata->op_sys_clock), GFP_KERNEL);
if (!pdata->op_sys_clock) {
rval = -ENOMEM;
goto out_err;
}
- asize /= sizeof(*pdata->op_sys_clock);
- rval = of_property_read_u64_array(
- ep, "link-frequencies", pdata->op_sys_clock, asize);
- if (rval) {
- dev_warn(dev, "can't get link-frequencies\n");
- goto out_err;
+ for (i = 0; i < bus_cfg->nr_of_link_frequencies; i++) {
+ pdata->op_sys_clock[i] = bus_cfg->link_frequencies[i];
+ dev_dbg(dev, "freq %d: %lld\n", i, pdata->op_sys_clock[i]);
}
- for (; asize > 0; asize--)
- dev_dbg(dev, "freq %d: %lld\n", asize - 1,
- pdata->op_sys_clock[asize - 1]);
-
+ v4l2_of_free_endpoint(bus_cfg);
of_node_put(ep);
return pdata;
out_err:
+ v4l2_of_free_endpoint(bus_cfg);
of_node_put(ep);
return NULL;
}
return buf[0] & 0xff; /* no sign-extension */
}
-static int imx074_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int imx074_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct imx074 *priv = to_imx074(client);
+
+ if (format->pad)
+ return -EINVAL;
dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
if (!fmt) {
+ /* MIPI CSI could have changed the format, double-check */
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
mf->code = imx074_colour_fmts[0].code;
mf->colorspace = imx074_colour_fmts[0].colorspace;
}
mf->height = IMX074_HEIGHT;
mf->field = V4L2_FIELD_NONE;
- return 0;
-}
-
-static int imx074_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct imx074 *priv = to_imx074(client);
-
- dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
-
- /* MIPI CSI could have changed the format, double-check */
- if (!imx074_find_datafmt(mf->code))
- return -EINVAL;
-
- imx074_try_fmt(sd, mf);
-
- priv->fmt = imx074_find_datafmt(mf->code);
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ priv->fmt = imx074_find_datafmt(mf->code);
+ else
+ cfg->try_fmt = *mf;
return 0;
}
-static int imx074_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int imx074_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct imx074 *priv = to_imx074(client);
const struct imx074_datafmt *fmt = priv->fmt;
+ if (format->pad)
+ return -EINVAL;
+
mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
mf->width = IMX074_WIDTH;
return 0;
}
-static int imx074_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int imx074_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if ((unsigned int)index >= ARRAY_SIZE(imx074_colour_fmts))
+ if (code->pad ||
+ (unsigned int)code->index >= ARRAY_SIZE(imx074_colour_fmts))
return -EINVAL;
- *code = imx074_colour_fmts[index].code;
+ code->code = imx074_colour_fmts[code->index].code;
return 0;
}
static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
.s_stream = imx074_s_stream,
- .s_mbus_fmt = imx074_s_fmt,
- .g_mbus_fmt = imx074_g_fmt,
- .try_mbus_fmt = imx074_try_fmt,
- .enum_mbus_fmt = imx074_enum_fmt,
.g_crop = imx074_g_crop,
.cropcap = imx074_cropcap,
.g_mbus_config = imx074_g_mbus_config,
.s_power = imx074_s_power,
};
+static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
+ .enum_mbus_code = imx074_enum_mbus_code,
+ .get_fmt = imx074_get_fmt,
+ .set_fmt = imx074_set_fmt,
+};
+
static struct v4l2_subdev_ops imx074_subdev_ops = {
.core = &imx074_subdev_core_ops,
.video = &imx074_subdev_video_ops,
+ .pad = &imx074_subdev_pad_ops,
};
static int imx074_video_probe(struct i2c_client *client)
/*
* The caller provides a supported format, as verified per
- * call to .try_mbus_fmt()
+ * call to .set_fmt(FORMAT_TRY).
*/
if (!ret)
ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
return 0;
}
-static int mt9m001_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m001_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
mf->width = mt9m001->rect.width;
mf->height = mt9m001->rect.height;
return ret;
}
-static int mt9m001_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m001_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
const struct mt9m001_datafmt *fmt;
+ if (format->pad)
+ return -EINVAL;
+
v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH,
MT9M001_MAX_WIDTH, 1,
&mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top,
mf->colorspace = fmt->colorspace;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return mt9m001_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
.s_power = mt9m001_s_power,
};
-static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9m001_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
- if (index >= mt9m001->num_fmts)
+ if (code->pad || code->index >= mt9m001->num_fmts)
return -EINVAL;
- *code = mt9m001->fmts[index].code;
+ code->code = mt9m001->fmts[code->index].code;
return 0;
}
static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
.s_stream = mt9m001_s_stream,
- .s_mbus_fmt = mt9m001_s_fmt,
- .g_mbus_fmt = mt9m001_g_fmt,
- .try_mbus_fmt = mt9m001_try_fmt,
.s_crop = mt9m001_s_crop,
.g_crop = mt9m001_g_crop,
.cropcap = mt9m001_cropcap,
- .enum_mbus_fmt = mt9m001_enum_fmt,
.g_mbus_config = mt9m001_g_mbus_config,
.s_mbus_config = mt9m001_s_mbus_config,
};
.g_skip_top_lines = mt9m001_g_skip_top_lines,
};
+static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
+ .enum_mbus_code = mt9m001_enum_mbus_code,
+ .get_fmt = mt9m001_get_fmt,
+ .set_fmt = mt9m001_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9m001_subdev_ops = {
.core = &mt9m001_subdev_core_ops,
.video = &mt9m001_subdev_video_ops,
.sensor = &mt9m001_subdev_sensor_ops,
+ .pad = &mt9m001_subdev_pad_ops,
};
static int mt9m001_probe(struct i2c_client *client,
return 0;
}
-static int mt9m111_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m111_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = mt9m111->width;
mf->height = mt9m111->height;
mf->code = mt9m111->fmt->code;
return ret;
}
-static int mt9m111_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9m111_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
const struct mt9m111_datafmt *fmt;
struct v4l2_rect *rect = &mt9m111->rect;
bool bayer;
+ int ret;
+
+ if (format->pad)
+ return -EINVAL;
fmt = mt9m111_find_datafmt(mt9m111, mf->code);
mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
- return 0;
-}
-
-static int mt9m111_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- const struct mt9m111_datafmt *fmt;
- struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
- struct v4l2_rect *rect = &mt9m111->rect;
- int ret;
-
- mt9m111_try_fmt(sd, mf);
- fmt = mt9m111_find_datafmt(mt9m111, mf->code);
- /* try_fmt() guarantees fmt != NULL && fmt->code == mf->code */
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code);
if (!ret)
#endif
};
-static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9m111_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
+ if (code->pad || code->index >= ARRAY_SIZE(mt9m111_colour_fmts))
return -EINVAL;
- *code = mt9m111_colour_fmts[index].code;
+ code->code = mt9m111_colour_fmts[code->index].code;
return 0;
}
}
static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
- .s_mbus_fmt = mt9m111_s_fmt,
- .g_mbus_fmt = mt9m111_g_fmt,
- .try_mbus_fmt = mt9m111_try_fmt,
.s_crop = mt9m111_s_crop,
.g_crop = mt9m111_g_crop,
.cropcap = mt9m111_cropcap,
- .enum_mbus_fmt = mt9m111_enum_fmt,
.g_mbus_config = mt9m111_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops mt9m111_subdev_pad_ops = {
+ .enum_mbus_code = mt9m111_enum_mbus_code,
+ .get_fmt = mt9m111_get_fmt,
+ .set_fmt = mt9m111_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9m111_subdev_ops = {
.core = &mt9m111_subdev_core_ops,
.video = &mt9m111_subdev_video_ops,
+ .pad = &mt9m111_subdev_pad_ops,
};
/*
/*
* The caller provides a supported format, as guaranteed by
- * .try_mbus_fmt(), soc_camera_s_crop() and soc_camera_cropcap()
+ * .set_fmt(FORMAT_TRY), soc_camera_s_crop() and soc_camera_cropcap()
*/
if (ret >= 0)
ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
return 0;
}
-static int mt9t031_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9t031_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t031 *mt9t031 = to_mt9t031(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = mt9t031->rect.width / mt9t031->xskip;
mf->height = mt9t031->rect.height / mt9t031->yskip;
mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
return 0;
}
-static int mt9t031_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+/*
+ * If a user window larger than sensor window is requested, we'll increase the
+ * sensor window.
+ */
+static int mt9t031_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t031 *mt9t031 = to_mt9t031(client);
u16 xskip, yskip;
struct v4l2_rect rect = mt9t031->rect;
+ if (format->pad)
+ return -EINVAL;
+
+ mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ mf->colorspace = V4L2_COLORSPACE_SRGB;
+ v4l_bound_align_image(
+ &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
+ &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
+
/*
- * try_fmt has put width and height within limits.
+ * Width and height are within limits.
* S_FMT: use binning and skipping for scaling
*/
xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH);
return mt9t031_set_params(client, &rect, xskip, yskip);
}
-/*
- * If a user window larger than sensor window is requested, we'll increase the
- * sensor window.
- */
-static int mt9t031_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- v4l_bound_align_image(
- &mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
- &mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
-
- mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
- mf->colorspace = V4L2_COLORSPACE_SRGB;
-
- return 0;
-}
-
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9t031_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
#endif
};
-static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9t031_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
return 0;
}
static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
.s_stream = mt9t031_s_stream,
- .s_mbus_fmt = mt9t031_s_fmt,
- .g_mbus_fmt = mt9t031_g_fmt,
- .try_mbus_fmt = mt9t031_try_fmt,
.s_crop = mt9t031_s_crop,
.g_crop = mt9t031_g_crop,
.cropcap = mt9t031_cropcap,
- .enum_mbus_fmt = mt9t031_enum_fmt,
.g_mbus_config = mt9t031_g_mbus_config,
.s_mbus_config = mt9t031_s_mbus_config,
};
.g_skip_top_lines = mt9t031_g_skip_top_lines,
};
+static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = {
+ .enum_mbus_code = mt9t031_enum_mbus_code,
+ .get_fmt = mt9t031_get_fmt,
+ .set_fmt = mt9t031_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9t031_subdev_ops = {
.core = &mt9t031_subdev_core_ops,
.video = &mt9t031_subdev_video_ops,
.sensor = &mt9t031_subdev_sensor_ops,
+ .pad = &mt9t031_subdev_pad_ops,
};
static int mt9t031_probe(struct i2c_client *client,
return mt9t112_set_params(priv, rect, priv->format->code);
}
-static int mt9t112_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9t112_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->frame.width;
mf->height = priv->frame.height;
mf->colorspace = priv->format->colorspace;
return ret;
}
-static int mt9t112_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9t112_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
unsigned int top, left;
int i;
+ if (format->pad)
+ return -EINVAL;
+
for (i = 0; i < priv->num_formats; i++)
if (mt9t112_cfmts[i].code == mf->code)
break;
mf->field = V4L2_FIELD_NONE;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return mt9t112_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
-static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9t112_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
- if (index >= priv->num_formats)
+ if (code->pad || code->index >= priv->num_formats)
return -EINVAL;
- *code = mt9t112_cfmts[index].code;
+ code->code = mt9t112_cfmts[code->index].code;
return 0;
}
static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
.s_stream = mt9t112_s_stream,
- .g_mbus_fmt = mt9t112_g_fmt,
- .s_mbus_fmt = mt9t112_s_fmt,
- .try_mbus_fmt = mt9t112_try_fmt,
.cropcap = mt9t112_cropcap,
.g_crop = mt9t112_g_crop,
.s_crop = mt9t112_s_crop,
- .enum_mbus_fmt = mt9t112_enum_fmt,
.g_mbus_config = mt9t112_g_mbus_config,
.s_mbus_config = mt9t112_s_mbus_config,
};
+static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = {
+ .enum_mbus_code = mt9t112_enum_mbus_code,
+ .get_fmt = mt9t112_get_fmt,
+ .set_fmt = mt9t112_set_fmt,
+};
+
/************************************************************************
i2c driver
************************************************************************/
static struct v4l2_subdev_ops mt9t112_subdev_ops = {
.core = &mt9t112_subdev_core_ops,
.video = &mt9t112_subdev_video_ops,
+ .pad = &mt9t112_subdev_pad_ops,
};
static int mt9t112_camera_probe(struct i2c_client *client)
return 0;
}
-static int mt9v022_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9v022_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = mt9v022->rect.width;
mf->height = mt9v022->rect.height;
mf->code = mt9v022->fmt->code;
/*
* The caller provides a supported format, as verified per call to
- * .try_mbus_fmt(), datawidth is from our supported format list
+ * .set_fmt(FORMAT_TRY), datawidth is from our supported format list
*/
switch (mf->code) {
case MEDIA_BUS_FMT_Y8_1X8:
return ret;
}
-static int mt9v022_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int mt9v022_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
const struct mt9v022_datafmt *fmt;
int align = mf->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
mf->code == MEDIA_BUS_FMT_SBGGR10_1X10;
+ if (format->pad)
+ return -EINVAL;
+
v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
MT9V022_MAX_WIDTH, align,
&mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top,
mf->colorspace = fmt->colorspace;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return mt9v022_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
.s_power = mt9v022_s_power,
};
-static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int mt9v022_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
- if (index >= mt9v022->num_fmts)
+ if (code->pad || code->index >= mt9v022->num_fmts)
return -EINVAL;
- *code = mt9v022->fmts[index].code;
+ code->code = mt9v022->fmts[code->index].code;
return 0;
}
static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
.s_stream = mt9v022_s_stream,
- .s_mbus_fmt = mt9v022_s_fmt,
- .g_mbus_fmt = mt9v022_g_fmt,
- .try_mbus_fmt = mt9v022_try_fmt,
.s_crop = mt9v022_s_crop,
.g_crop = mt9v022_g_crop,
.cropcap = mt9v022_cropcap,
- .enum_mbus_fmt = mt9v022_enum_fmt,
.g_mbus_config = mt9v022_g_mbus_config,
.s_mbus_config = mt9v022_s_mbus_config,
};
.g_skip_top_lines = mt9v022_g_skip_top_lines,
};
+static const struct v4l2_subdev_pad_ops mt9v022_subdev_pad_ops = {
+ .enum_mbus_code = mt9v022_enum_mbus_code,
+ .get_fmt = mt9v022_get_fmt,
+ .set_fmt = mt9v022_set_fmt,
+};
+
static struct v4l2_subdev_ops mt9v022_subdev_ops = {
.core = &mt9v022_subdev_core_ops,
.video = &mt9v022_subdev_video_ops,
.sensor = &mt9v022_subdev_sensor_ops,
+ .pad = &mt9v022_subdev_pad_ops,
};
static int mt9v022_probe(struct i2c_client *client,
return ret;
}
-static int ov2640_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov2640_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
+ if (format->pad)
+ return -EINVAL;
+
if (!priv->win) {
u32 width = SVGA_WIDTH, height = SVGA_HEIGHT;
priv->win = ov2640_select_win(&width, &height);
return 0;
}
-static int ov2640_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov2640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
- int ret;
+ if (format->pad)
+ return -EINVAL;
- switch (mf->code) {
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
- mf->colorspace = V4L2_COLORSPACE_SRGB;
- break;
- default:
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
- mf->colorspace = V4L2_COLORSPACE_JPEG;
- }
-
- ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code);
-
- return ret;
-}
-
-static int ov2640_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
/*
* select suitable win, but don't store it
*/
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov2640_set_params(client, &mf->width,
+ &mf->height, mf->code);
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov2640_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov2640_codes))
return -EINVAL;
- *code = ov2640_codes[index];
+ code->code = ov2640_codes[code->index];
return 0;
}
static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
.s_stream = ov2640_s_stream,
- .g_mbus_fmt = ov2640_g_fmt,
- .s_mbus_fmt = ov2640_s_fmt,
- .try_mbus_fmt = ov2640_try_fmt,
.cropcap = ov2640_cropcap,
.g_crop = ov2640_g_crop,
- .enum_mbus_fmt = ov2640_enum_fmt,
.g_mbus_config = ov2640_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
+ .enum_mbus_code = ov2640_enum_mbus_code,
+ .get_fmt = ov2640_get_fmt,
+ .set_fmt = ov2640_set_fmt,
+};
+
static struct v4l2_subdev_ops ov2640_subdev_ops = {
.core = &ov2640_subdev_core_ops,
.video = &ov2640_subdev_video_ops,
+ .pad = &ov2640_subdev_pad_ops,
};
/* OF probe functions */
return ret;
}
-static int ov5642_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov5642_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov5642 *priv = to_ov5642(client);
const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->crop_rect.width;
mf->height = priv->crop_rect.height;
if (!fmt) {
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
mf->code = ov5642_colour_fmts[0].code;
mf->colorspace = ov5642_colour_fmts[0].colorspace;
}
mf->field = V4L2_FIELD_NONE;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ priv->fmt = ov5642_find_datafmt(mf->code);
+ else
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov5642_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct ov5642 *priv = to_ov5642(client);
-
- /* MIPI CSI could have changed the format, double-check */
- if (!ov5642_find_datafmt(mf->code))
- return -EINVAL;
-
- ov5642_try_fmt(sd, mf);
- priv->fmt = ov5642_find_datafmt(mf->code);
-
- return 0;
-}
-
-static int ov5642_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov5642_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov5642 *priv = to_ov5642(client);
const struct ov5642_datafmt *fmt = priv->fmt;
+ if (format->pad)
+ return -EINVAL;
+
mf->code = fmt->code;
mf->colorspace = fmt->colorspace;
mf->width = priv->crop_rect.width;
return 0;
}
-static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov5642_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov5642_colour_fmts))
+ if (code->pad || code->index >= ARRAY_SIZE(ov5642_colour_fmts))
return -EINVAL;
- *code = ov5642_colour_fmts[index].code;
+ code->code = ov5642_colour_fmts[code->index].code;
return 0;
}
}
static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
- .s_mbus_fmt = ov5642_s_fmt,
- .g_mbus_fmt = ov5642_g_fmt,
- .try_mbus_fmt = ov5642_try_fmt,
- .enum_mbus_fmt = ov5642_enum_fmt,
.s_crop = ov5642_s_crop,
.g_crop = ov5642_g_crop,
.cropcap = ov5642_cropcap,
.g_mbus_config = ov5642_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ov5642_subdev_pad_ops = {
+ .enum_mbus_code = ov5642_enum_mbus_code,
+ .get_fmt = ov5642_get_fmt,
+ .set_fmt = ov5642_set_fmt,
+};
+
static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
.s_power = ov5642_s_power,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static struct v4l2_subdev_ops ov5642_subdev_ops = {
.core = &ov5642_subdev_core_ops,
.video = &ov5642_subdev_video_ops,
+ .pad = &ov5642_subdev_pad_ops,
};
static int ov5642_video_probe(struct i2c_client *client)
return 0;
}
-static int ov6650_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov6650_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov6650 *priv = to_ov6650(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->rect.width >> priv->half_scale;
mf->height = priv->rect.height >> priv->half_scale;
mf->code = priv->code;
mf->width = priv->rect.width >> half_scale;
mf->height = priv->rect.height >> half_scale;
}
-
return ret;
}
-static int ov6650_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov6650_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov6650 *priv = to_ov6650(client);
+ if (format->pad)
+ return -EINVAL;
+
if (is_unscaled_ok(mf->width, mf->height, &priv->rect))
v4l_bound_align_image(&mf->width, 2, W_CIF, 1,
&mf->height, 2, H_CIF, 1, 0);
break;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov6650_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
+
return 0;
}
-static int ov6650_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov6650_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov6650_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov6650_codes))
return -EINVAL;
- *code = ov6650_codes[index];
+ code->code = ov6650_codes[code->index];
return 0;
}
static struct v4l2_subdev_video_ops ov6650_video_ops = {
.s_stream = ov6650_s_stream,
- .g_mbus_fmt = ov6650_g_fmt,
- .s_mbus_fmt = ov6650_s_fmt,
- .try_mbus_fmt = ov6650_try_fmt,
- .enum_mbus_fmt = ov6650_enum_fmt,
.cropcap = ov6650_cropcap,
.g_crop = ov6650_g_crop,
.s_crop = ov6650_s_crop,
.s_mbus_config = ov6650_s_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ov6650_pad_ops = {
+ .enum_mbus_code = ov6650_enum_mbus_code,
+ .get_fmt = ov6650_get_fmt,
+ .set_fmt = ov6650_set_fmt,
+};
+
static struct v4l2_subdev_ops ov6650_subdev_ops = {
.core = &ov6650_core_ops,
.video = &ov6650_video_ops,
+ .pad = &ov6650_pad_ops,
};
/*
return 0;
}
-static int ov772x_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov772x_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct ov772x_priv *priv = to_ov772x(sd);
+ if (format->pad)
+ return -EINVAL;
+
mf->width = priv->win->rect.width;
mf->height = priv->win->rect.height;
mf->code = priv->cfmt->code;
return 0;
}
-static int ov772x_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov772x_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
const struct ov772x_color_format *cfmt;
const struct ov772x_win_size *win;
+ if (format->pad)
+ return -EINVAL;
+
ov772x_select_params(mf, &cfmt, &win);
mf->code = cfmt->code;
mf->field = V4L2_FIELD_NONE;
mf->colorspace = cfmt->colorspace;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov772x_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
.s_power = ov772x_s_power,
};
-static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov772x_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov772x_cfmts))
+ if (code->pad || code->index >= ARRAY_SIZE(ov772x_cfmts))
return -EINVAL;
- *code = ov772x_cfmts[index].code;
+ code->code = ov772x_cfmts[code->index].code;
return 0;
}
static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
.s_stream = ov772x_s_stream,
- .g_mbus_fmt = ov772x_g_fmt,
- .s_mbus_fmt = ov772x_s_fmt,
- .try_mbus_fmt = ov772x_try_fmt,
.cropcap = ov772x_cropcap,
.g_crop = ov772x_g_crop,
- .enum_mbus_fmt = ov772x_enum_fmt,
.g_mbus_config = ov772x_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ov772x_subdev_pad_ops = {
+ .enum_mbus_code = ov772x_enum_mbus_code,
+ .get_fmt = ov772x_get_fmt,
+ .set_fmt = ov772x_set_fmt,
+};
+
static struct v4l2_subdev_ops ov772x_subdev_ops = {
.core = &ov772x_subdev_core_ops,
.video = &ov772x_subdev_video_ops,
+ .pad = &ov772x_subdev_pad_ops,
};
/*
return ret;
}
-static int ov9640_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov9640_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
ov9640_res_roundup(&mf->width, &mf->height);
mf->field = V4L2_FIELD_NONE;
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov9640_s_fmt(sd, mf);
+
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov9640_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov9640_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov9640_codes))
return -EINVAL;
- *code = ov9640_codes[index];
+ code->code = ov9640_codes[code->index];
return 0;
}
static struct v4l2_subdev_video_ops ov9640_video_ops = {
.s_stream = ov9640_s_stream,
- .s_mbus_fmt = ov9640_s_fmt,
- .try_mbus_fmt = ov9640_try_fmt,
- .enum_mbus_fmt = ov9640_enum_fmt,
.cropcap = ov9640_cropcap,
.g_crop = ov9640_g_crop,
.g_mbus_config = ov9640_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops ov9640_pad_ops = {
+ .enum_mbus_code = ov9640_enum_mbus_code,
+ .set_fmt = ov9640_set_fmt,
+};
+
static struct v4l2_subdev_ops ov9640_subdev_ops = {
.core = &ov9640_core_ops,
.video = &ov9640_video_ops,
+ .pad = &ov9640_pad_ops,
};
/*
return ret;
}
-static int ov9740_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int ov9740_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
+
+ if (format->pad)
+ return -EINVAL;
+
ov9740_res_roundup(&mf->width, &mf->height);
mf->field = V4L2_FIELD_NONE;
mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
mf->colorspace = V4L2_COLORSPACE_SRGB;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return ov9740_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
-static int ov9740_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int ov9740_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(ov9740_codes))
+ if (code->pad || code->index >= ARRAY_SIZE(ov9740_codes))
return -EINVAL;
- *code = ov9740_codes[index];
+ code->code = ov9740_codes[code->index];
return 0;
}
static struct v4l2_subdev_video_ops ov9740_video_ops = {
.s_stream = ov9740_s_stream,
- .s_mbus_fmt = ov9740_s_fmt,
- .try_mbus_fmt = ov9740_try_fmt,
- .enum_mbus_fmt = ov9740_enum_fmt,
.cropcap = ov9740_cropcap,
.g_crop = ov9740_g_crop,
.g_mbus_config = ov9740_g_mbus_config,
#endif
};
+static const struct v4l2_subdev_pad_ops ov9740_pad_ops = {
+ .enum_mbus_code = ov9740_enum_mbus_code,
+ .set_fmt = ov9740_set_fmt,
+};
+
static struct v4l2_subdev_ops ov9740_subdev_ops = {
- .core = &ov9740_core_ops,
- .video = &ov9740_video_ops,
+ .core = &ov9740_core_ops,
+ .video = &ov9740_video_ops,
+ .pad = &ov9740_pad_ops,
};
static const struct v4l2_ctrl_ops ov9740_ctrl_ops = {
return 0;
}
-static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int rj54n1_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
+ if (code->pad || code->index >= ARRAY_SIZE(rj54n1_colour_fmts))
return -EINVAL;
- *code = rj54n1_colour_fmts[index].code;
+ code->code = rj54n1_colour_fmts[code->index].code;
return 0;
}
return 0;
}
-static int rj54n1_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int rj54n1_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct rj54n1 *rj54n1 = to_rj54n1(client);
+ if (format->pad)
+ return -EINVAL;
+
mf->code = rj54n1->fmt->code;
mf->colorspace = rj54n1->fmt->colorspace;
mf->field = V4L2_FIELD_NONE;
return ret;
}
-static int rj54n1_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int rj54n1_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct rj54n1 *rj54n1 = to_rj54n1(client);
const struct rj54n1_datafmt *fmt;
+ int output_w, output_h, max_w, max_h,
+ input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
int align = mf->code == MEDIA_BUS_FMT_SBGGR10_1X10 ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE ||
mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE;
+ int ret;
+
+ if (format->pad)
+ return -EINVAL;
dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
__func__, mf->code, mf->width, mf->height);
v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align,
&mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0);
- return 0;
-}
-
-static int rj54n1_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct i2c_client *client = v4l2_get_subdevdata(sd);
- struct rj54n1 *rj54n1 = to_rj54n1(client);
- const struct rj54n1_datafmt *fmt;
- int output_w, output_h, max_w, max_h,
- input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
- int ret;
-
- /*
- * The host driver can call us without .try_fmt(), so, we have to take
- * care ourseleves
- */
- rj54n1_try_fmt(sd, mf);
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
/*
* Verify if the sensor has just been powered on. TODO: replace this
return ret;
}
- dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
- __func__, mf->code, mf->width, mf->height);
-
/* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
switch (mf->code) {
case MEDIA_BUS_FMT_YUYV8_2X8:
static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
.s_stream = rj54n1_s_stream,
- .s_mbus_fmt = rj54n1_s_fmt,
- .g_mbus_fmt = rj54n1_g_fmt,
- .try_mbus_fmt = rj54n1_try_fmt,
- .enum_mbus_fmt = rj54n1_enum_fmt,
.g_crop = rj54n1_g_crop,
.s_crop = rj54n1_s_crop,
.cropcap = rj54n1_cropcap,
.s_mbus_config = rj54n1_s_mbus_config,
};
+static const struct v4l2_subdev_pad_ops rj54n1_subdev_pad_ops = {
+ .enum_mbus_code = rj54n1_enum_mbus_code,
+ .get_fmt = rj54n1_get_fmt,
+ .set_fmt = rj54n1_set_fmt,
+};
+
static struct v4l2_subdev_ops rj54n1_subdev_ops = {
.core = &rj54n1_subdev_core_ops,
.video = &rj54n1_subdev_video_ops,
+ .pad = &rj54n1_subdev_pad_ops,
};
/*
return 0;
}
-static int tw9910_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int tw9910_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct tw9910_priv *priv = to_tw9910(client);
+ if (format->pad)
+ return -EINVAL;
+
if (!priv->scale) {
priv->scale = tw9910_select_norm(priv->norm, 640, 480);
if (!priv->scale)
return ret;
}
-static int tw9910_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int tw9910_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct tw9910_priv *priv = to_tw9910(client);
const struct tw9910_scale_ctrl *scale;
+ if (format->pad)
+ return -EINVAL;
+
if (V4L2_FIELD_ANY == mf->field) {
mf->field = V4L2_FIELD_INTERLACED_BT;
} else if (V4L2_FIELD_INTERLACED_BT != mf->field) {
mf->width = scale->width;
mf->height = scale->height;
+ if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+ return tw9910_s_fmt(sd, mf);
+ cfg->try_fmt = *mf;
return 0;
}
.s_power = tw9910_s_power,
};
-static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int tw9910_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
return 0;
}
.s_std = tw9910_s_std,
.g_std = tw9910_g_std,
.s_stream = tw9910_s_stream,
- .g_mbus_fmt = tw9910_g_fmt,
- .s_mbus_fmt = tw9910_s_fmt,
- .try_mbus_fmt = tw9910_try_fmt,
.cropcap = tw9910_cropcap,
.g_crop = tw9910_g_crop,
- .enum_mbus_fmt = tw9910_enum_fmt,
.g_mbus_config = tw9910_g_mbus_config,
.s_mbus_config = tw9910_s_mbus_config,
.g_tvnorms = tw9910_g_tvnorms,
};
+static const struct v4l2_subdev_pad_ops tw9910_subdev_pad_ops = {
+ .enum_mbus_code = tw9910_enum_mbus_code,
+ .get_fmt = tw9910_get_fmt,
+ .set_fmt = tw9910_set_fmt,
+};
+
static struct v4l2_subdev_ops tw9910_subdev_ops = {
.core = &tw9910_subdev_core_ops,
.video = &tw9910_subdev_video_ops,
+ .pad = &tw9910_subdev_pad_ops,
};
/*
return 0;
}
-static int sr030pc30_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int sr030pc30_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (!code || index >= ARRAY_SIZE(sr030pc30_formats))
+ if (!code || code->pad ||
+ code->index >= ARRAY_SIZE(sr030pc30_formats))
return -EINVAL;
- *code = sr030pc30_formats[index].code;
+ code->code = sr030pc30_formats[code->index].code;
return 0;
}
-static int sr030pc30_g_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int sr030pc30_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *mf;
struct sr030pc30_info *info = to_sr030pc30(sd);
int ret;
- if (!mf)
+ if (!format || format->pad)
return -EINVAL;
+ mf = &format->format;
+
if (!info->curr_win || !info->curr_fmt) {
ret = sr030pc30_set_params(sd);
if (ret)
}
/* Return nearest media bus frame format. */
-static int sr030pc30_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int sr030pc30_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
- if (!sd || !mf)
- return -EINVAL;
-
- try_fmt(sd, mf);
- return 0;
-}
+ struct sr030pc30_info *info = sd ? to_sr030pc30(sd) : NULL;
+ const struct sr030pc30_format *fmt;
+ struct v4l2_mbus_framefmt *mf;
-static int sr030pc30_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct sr030pc30_info *info = to_sr030pc30(sd);
+ if (!sd || !format)
+ return -EINVAL;
- if (!sd || !mf)
+ mf = &format->format;
+ if (format->pad)
return -EINVAL;
- info->curr_fmt = try_fmt(sd, mf);
+ fmt = try_fmt(sd, mf);
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
+
+ info->curr_fmt = fmt;
return sr030pc30_set_params(sd);
}
.querymenu = v4l2_subdev_querymenu,
};
-static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
- .g_mbus_fmt = sr030pc30_g_fmt,
- .s_mbus_fmt = sr030pc30_s_fmt,
- .try_mbus_fmt = sr030pc30_try_fmt,
- .enum_mbus_fmt = sr030pc30_enum_fmt,
+static const struct v4l2_subdev_pad_ops sr030pc30_pad_ops = {
+ .enum_mbus_code = sr030pc30_enum_mbus_code,
+ .get_fmt = sr030pc30_get_fmt,
+ .set_fmt = sr030pc30_set_fmt,
};
static const struct v4l2_subdev_ops sr030pc30_ops = {
.core = &sr030pc30_core_ops,
- .video = &sr030pc30_video_ops,
+ .pad = &sr030pc30_pad_ops,
};
/*
return -EINVAL;
}
- /* FIXME: it seems that the shadow bytes are wrong bellow !*/
+ /* FIXME: it seems that the shadow bytes are wrong below !*/
/* update our shadow register set; print bytes if (debug > 0) */
v4l2_dbg(1, debug, sd, "chip_cmd(%s): reg=%d, data:",
return err;
}
-/**
- * tvp514x_enum_mbus_fmt() - V4L2 decoder interface handler for enum_mbus_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @index: index of pixelcode to retrieve
- * @code: receives the pixelcode
- *
- * Enumerates supported mediabus formats
- */
-static int
-tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
-{
- if (index)
- return -EINVAL;
-
- *code = MEDIA_BUS_FMT_YUYV10_2X10;
- return 0;
-}
-
-/**
- * tvp514x_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to the mediabus format structure
- *
- * Negotiates the image capture size and mediabus format.
- */
-static int
-tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct tvp514x_decoder *decoder = to_decoder(sd);
- enum tvp514x_std current_std;
-
- if (f == NULL)
- return -EINVAL;
-
- /* Calculate height and width based on current standard */
- current_std = decoder->current_std;
-
- f->code = MEDIA_BUS_FMT_YUYV8_2X8;
- f->width = decoder->std_list[current_std].width;
- f->height = decoder->std_list[current_std].height;
- f->field = V4L2_FIELD_INTERLACED;
- f->colorspace = V4L2_COLORSPACE_SMPTE170M;
- v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
- f->width, f->height);
- return 0;
-}
-
/**
* tvp514x_g_parm() - V4L2 decoder interface handler for g_parm
* @sd: pointer to standard V4L2 sub-device structure
struct tvp514x_decoder *decoder = to_decoder(sd);
__u32 which = format->which;
+ if (format->pad)
+ return -EINVAL;
+
if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
format->format = decoder->format;
return 0;
.s_std = tvp514x_s_std,
.s_routing = tvp514x_s_routing,
.querystd = tvp514x_querystd,
- .enum_mbus_fmt = tvp514x_enum_mbus_fmt,
- .g_mbus_fmt = tvp514x_mbus_fmt,
- .try_mbus_fmt = tvp514x_mbus_fmt,
- .s_mbus_fmt = tvp514x_mbus_fmt,
.g_parm = tvp514x_g_parm,
.s_parm = tvp514x_s_parm,
.s_stream = tvp514x_s_stream,
}
}
-static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ code->code = MEDIA_BUS_FMT_UYVY8_2X8;
return 0;
}
-static int tvp5150_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *f)
+static int tvp5150_fill_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *f;
struct tvp5150 *decoder = to_tvp5150(sd);
- if (f == NULL)
+ if (!format || format->pad)
return -EINVAL;
+ f = &format->format;
+
tvp5150_reset(sd, 0);
f->width = decoder->rect.width;
static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
.s_std = tvp5150_s_std,
.s_routing = tvp5150_s_routing,
- .enum_mbus_fmt = tvp5150_enum_mbus_fmt,
- .s_mbus_fmt = tvp5150_mbus_fmt,
- .try_mbus_fmt = tvp5150_mbus_fmt,
- .g_mbus_fmt = tvp5150_mbus_fmt,
.s_crop = tvp5150_s_crop,
.g_crop = tvp5150_g_crop,
.cropcap = tvp5150_cropcap,
.s_raw_fmt = tvp5150_s_raw_fmt,
};
+static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = {
+ .enum_mbus_code = tvp5150_enum_mbus_code,
+ .set_fmt = tvp5150_fill_fmt,
+ .get_fmt = tvp5150_fill_fmt,
+};
+
static const struct v4l2_subdev_ops tvp5150_ops = {
.core = &tvp5150_core_ops,
.tuner = &tvp5150_tuner_ops,
.video = &tvp5150_video_ops,
.vbi = &tvp5150_vbi_ops,
+ .pad = &tvp5150_pad_ops,
};
return -EINVAL;
}
-/*
- * tvp7002_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to mediabus format structure
- *
- * Negotiate the image capture size and mediabus format.
- * There is only one possible format, so this single function works for
- * get, set and try.
- */
-static int tvp7002_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
- struct tvp7002 *device = to_tvp7002(sd);
- const struct v4l2_bt_timings *bt = &device->current_timings->timings.bt;
-
- f->width = bt->width;
- f->height = bt->height;
- f->code = MEDIA_BUS_FMT_YUYV10_1X20;
- f->field = device->current_timings->scanmode;
- f->colorspace = device->current_timings->color_space;
-
- v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d",
- f->width, f->height);
- return 0;
-}
-
/*
* tvp7002_query_dv() - query DV timings
* @sd: pointer to standard V4L2 sub-device structure
}
#endif
-/*
- * tvp7002_enum_mbus_fmt() - Enum supported mediabus formats
- * @sd: pointer to standard V4L2 sub-device structure
- * @index: format index
- * @code: pointer to mediabus format
- *
- * Enumerate supported mediabus formats.
- */
-
-static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
-{
- /* Check requested format index is within range */
- if (index)
- return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV10_1X20;
- return 0;
-}
-
/*
* tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream
* @sd: pointer to standard V4L2 sub-device structure
.s_dv_timings = tvp7002_s_dv_timings,
.query_dv_timings = tvp7002_query_dv_timings,
.s_stream = tvp7002_s_stream,
- .g_mbus_fmt = tvp7002_mbus_fmt,
- .try_mbus_fmt = tvp7002_mbus_fmt,
- .s_mbus_fmt = tvp7002_mbus_fmt,
- .enum_mbus_fmt = tvp7002_enum_mbus_fmt,
};
/* media pad related operation handlers */
return 0;
}
-static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+static int vs6624_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
- if (index >= ARRAY_SIZE(vs6624_formats))
+ if (code->pad || code->index >= ARRAY_SIZE(vs6624_formats))
return -EINVAL;
- *code = vs6624_formats[index].mbus_code;
+ code->code = vs6624_formats[code->index].mbus_code;
return 0;
}
-static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int vs6624_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
+ struct vs6624 *sensor = to_vs6624(sd);
int index;
+ if (format->pad)
+ return -EINVAL;
+
for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
if (vs6624_formats[index].mbus_code == fmt->code)
break;
fmt->height = fmt->height & (~3);
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = vs6624_formats[index].colorspace;
- return 0;
-}
-
-static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
-{
- struct vs6624 *sensor = to_vs6624(sd);
- int ret;
- ret = vs6624_try_mbus_fmt(sd, fmt);
- if (ret)
- return ret;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *fmt;
+ return 0;
+ }
/* set image format */
switch (fmt->code) {
return 0;
}
-static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int vs6624_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct vs6624 *sensor = to_vs6624(sd);
- *fmt = sensor->fmt;
+ if (format->pad)
+ return -EINVAL;
+
+ format->format = sensor->fmt;
return 0;
}
};
static const struct v4l2_subdev_video_ops vs6624_video_ops = {
- .enum_mbus_fmt = vs6624_enum_mbus_fmt,
- .try_mbus_fmt = vs6624_try_mbus_fmt,
- .s_mbus_fmt = vs6624_s_mbus_fmt,
- .g_mbus_fmt = vs6624_g_mbus_fmt,
.s_parm = vs6624_s_parm,
.g_parm = vs6624_g_parm,
.s_stream = vs6624_s_stream,
};
+static const struct v4l2_subdev_pad_ops vs6624_pad_ops = {
+ .enum_mbus_code = vs6624_enum_mbus_code,
+ .get_fmt = vs6624_get_fmt,
+ .set_fmt = vs6624_set_fmt,
+};
+
static const struct v4l2_subdev_ops vs6624_ops = {
.core = &vs6624_core_ops,
.video = &vs6624_video_ops,
+ .pad = &vs6624_pad_ops,
};
static int vs6624_probe(struct i2c_client *client,
source "drivers/media/pci/saa7146/Kconfig"
source "drivers/media/pci/solo6x10/Kconfig"
source "drivers/media/pci/tw68/Kconfig"
+source "drivers/media/pci/dt3155/Kconfig"
endif
if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
obj-$(CONFIG_VIDEO_TW68) += tw68/
+obj-$(CONFIG_VIDEO_DT3155) += dt3155/
obj-$(CONFIG_VIDEO_MEYE) += meye/
obj-$(CONFIG_STA2X11_VIP) += sta2x11/
obj-$(CONFIG_VIDEO_SOLO6X10) += solo6x10/
void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned int con = 0;
+ unsigned int con;
- if (set) {
- gpio_inout(0x300, 0x300);
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- con = 0x000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x300;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x200;
-/* if (t->audmode & V4L2_TUNER_MODE_MONO)
- * con = 0x100; */
- gpio_bits(0x300, con);
- } else {
- t->audmode = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ gpio_inout(0x300, 0x300);
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG1:
+ default:
+ con = 0x000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x300;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ con = 0x200;
+ break;
}
+ gpio_bits(0x300, con);
}
void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
val = gpio_read();
if (set) {
- con = 0x000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2) {
- if (t->audmode & V4L2_TUNER_MODE_LANG1) {
- /* LANG1 + LANG2 */
- con = 0x100;
- }
- else {
- /* LANG2 */
- con = 0x300;
- }
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x300;
+ break;
+ case V4L2_TUNER_MODE_LANG1_LANG2:
+ con = 0x100;
+ break;
+ default:
+ con = 0x000;
+ break;
}
if (con != (val & 0x300)) {
gpio_bits(0x300, con);
if (bttv_gpio)
- bttv_gpio_tracking(btv,"gvbctv5pci");
+ bttv_gpio_tracking(btv, "gvbctv5pci");
}
} else {
switch (val & 0x70) {
case 0x10:
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
break;
case 0x30:
t->rxsubchans = V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
break;
case 0x50:
t->rxsubchans = V4L2_TUNER_SUB_LANG1;
+ t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
break;
case 0x60:
t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ t->audmode = V4L2_TUNER_MODE_STEREO;
break;
case 0x70:
t->rxsubchans = V4L2_TUNER_SUB_MONO;
+ t->audmode = V4L2_TUNER_MODE_MONO;
break;
default:
t->rxsubchans = V4L2_TUNER_SUB_MONO |
V4L2_TUNER_SUB_STEREO |
V4L2_TUNER_SUB_LANG1 |
V4L2_TUNER_SUB_LANG2;
+ t->audmode = V4L2_TUNER_MODE_LANG1;
}
- t->audmode = V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- int val = 0;
+ int val;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x02;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- val = 0x01;
- if (val) {
- gpio_bits(0x03,val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"avermedia");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2: /* SAP */
+ val = 0x02;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x01;
+ break;
+ default:
return;
}
+ gpio_bits(0x03, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "avermedia");
}
{
int val = 0;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x01;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* STEREO */
- val = 0x02;
- btaor(val, ~0x03, BT848_GPIO_DATA);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"avermedia");
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2: /* SAP */
+ val = 0x01;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x02;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ btaor(val, ~0x03, BT848_GPIO_DATA);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "avermedia");
}
/* Lifetec 9415 handling */
return;
}
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* A2 SAP */
- val = 0x0080;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
- val = 0x0880;
- if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
- (t->audmode & V4L2_TUNER_MODE_MONO))
- val = 0;
- gpio_bits(0x0880, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"lt9415");
- } else {
- /* autodetect doesn't work with this card :-( */
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2: /* A2 SAP */
+ val = 0x0080;
+ break;
+ case V4L2_TUNER_MODE_STEREO: /* A2 stereo */
+ val = 0x0880;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ gpio_bits(0x0880, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "lt9415");
}
/* TDA9821 on TerraTV+ Bt848, Bt878 */
{
unsigned int con = 0;
- if (set) {
- gpio_inout(0x180000,0x180000);
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x080000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x180000;
- gpio_bits(0x180000, con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"terratv");
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ gpio_inout(0x180000, 0x180000);
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x080000;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ con = 0x180000;
+ break;
+ default:
+ con = 0;
+ break;
}
+ gpio_bits(0x180000, con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "terratv");
}
void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned long val = 0;
+ unsigned long val;
- if (set) {
- /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
- if (t->audmode & V4L2_TUNER_MODE_MONO) /* Mono */
- val = 0x420000;
- if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
- val = 0x420000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
- val = 0x410000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO) /* Stereo */
- val = 0x020000;
- if (val) {
- gpio_bits(0x430000, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"winfast2000");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ case V4L2_TUNER_MODE_LANG1:
+ val = 0x420000;
+ break;
+ case V4L2_TUNER_MODE_LANG2: /* SAP */
+ val = 0x410000;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x020000;
+ break;
+ default:
+ return;
+ }
+
+ gpio_bits(0x430000, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "winfast2000");
}
/*
if (btv->radio_user)
return;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO) {
- val = 0x01;
- }
- if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
- || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
- val = 0x02;
- }
- if (val) {
- gpio_bits(0x03,val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"pvbt878p9b");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ val = 0x01;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ case V4L2_TUNER_MODE_LANG2:
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x02;
+ break;
+ default:
+ return;
+ }
+
+ gpio_bits(0x03, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "pvbt878p9b");
}
/*
*/
void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned int val = 0xffff;
+ unsigned int val;
if (btv->radio_user)
return;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO) {
- val = 0x0000;
- }
- if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
- || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
- val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
- }
- if (val != 0xffff) {
- gpio_bits(0x1800, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"fv2000s");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ val = 0x0000;
+ break;
+ case V4L2_TUNER_MODE_LANG1:
+ case V4L2_TUNER_MODE_LANG2:
+ case V4L2_TUNER_MODE_STEREO:
+ val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
+ break;
+ default:
+ return;
+ }
+ gpio_bits(0x1800, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "fv2000s");
}
/*
*/
void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
- unsigned long val = 0;
+ unsigned long val;
- if (set) {
- if (t->audmode & V4L2_TUNER_MODE_MONO)
- val = 0x040000;
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- val = 0;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- val = 0x100000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- val = 0;
- if (val) {
- gpio_bits(0x140000, val);
- if (bttv_gpio)
- bttv_gpio_tracking(btv,"windvr");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
+ }
+
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_MONO:
+ val = 0x040000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ val = 0x100000;
+ break;
+ default:
+ return;
}
+
+ gpio_bits(0x140000, val);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "windvr");
}
/*
/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
- if (set) {
- /* btor(***, BT848_GPIO_OUT_EN); */
- if (t->audmode & V4L2_TUNER_MODE_LANG1)
- con = 0x00000000;
- if (t->audmode & V4L2_TUNER_MODE_LANG2)
- con = 0x00180000;
- if (t->audmode & V4L2_TUNER_MODE_STEREO)
- con = 0x00000000;
- if (t->audmode & V4L2_TUNER_MODE_MONO)
- con = 0x00060000;
- if (con != 0xffffff) {
- gpio_bits(0x1e0000,con);
- if (bttv_gpio)
- bttv_gpio_tracking(btv, "adtvk503");
- }
- } else {
- t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
- V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+ if (!set) {
+ /* Not much to do here */
+ t->audmode = V4L2_TUNER_MODE_LANG1;
+ t->rxsubchans = V4L2_TUNER_SUB_MONO |
+ V4L2_TUNER_SUB_STEREO |
+ V4L2_TUNER_SUB_LANG1 |
+ V4L2_TUNER_SUB_LANG2;
+
+ return;
}
+
+ /* btor(***, BT848_GPIO_OUT_EN); */
+ switch (t->audmode) {
+ case V4L2_TUNER_MODE_LANG1:
+ con = 0x00000000;
+ break;
+ case V4L2_TUNER_MODE_LANG2:
+ con = 0x00180000;
+ break;
+ case V4L2_TUNER_MODE_STEREO:
+ con = 0x00000000;
+ break;
+ case V4L2_TUNER_MODE_MONO:
+ con = 0x00060000;
+ break;
+ default:
+ return;
+ }
+
+ gpio_bits(0x1e0000, con);
+ if (bttv_gpio)
+ bttv_gpio_tracking(btv, "adtvk503");
}
fh->ov.w.height = fb->fmt.height;
btv->init.ov.w.width = fb->fmt.width;
btv->init.ov.w.height = fb->fmt.height;
- kfree(fh->ov.clips);
+
+ kfree(fh->ov.clips);
fh->ov.clips = NULL;
fh->ov.nclips = 0;
iounmap(btv->bt848_mmio);
release_mem_region(pci_resource_start(btv->c.pci,0),
pci_resource_len(btv->c.pci,0));
+ pci_disable_device(btv->c.pci);
return result;
}
iounmap(btv->bt848_mmio);
release_mem_region(pci_resource_start(btv->c.pci,0),
pci_resource_len(btv->c.pci,0));
+ pci_disable_device(btv->c.pci);
v4l2_device_unregister(&btv->c.v4l2_dev);
bttvs[btv->c.nr] = NULL;
return 0;
}
-static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+static int cx18_av_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct cx18_av_state *state = to_cx18_av_state(sd);
struct cx18 *cx = v4l2_get_subdevdata(sd);
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
return -ERANGE;
}
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
VSC &= 0x1fff;
.s_std = cx18_av_s_std,
.s_routing = cx18_av_s_video_routing,
.s_stream = cx18_av_s_stream,
- .s_mbus_fmt = cx18_av_s_mbus_fmt,
};
static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
.s_raw_fmt = cx18_av_s_raw_fmt,
};
+static const struct v4l2_subdev_pad_ops cx18_av_pad_ops = {
+ .set_fmt = cx18_av_set_fmt,
+};
+
static const struct v4l2_subdev_ops cx18_av_ops = {
.core = &cx18_av_general_ops,
.tuner = &cx18_av_tuner_ops,
.audio = &cx18_av_audio_ops,
.video = &cx18_av_video_ops,
.vbi = &cx18_av_vbi_ops,
+ .pad = &cx18_av_pad_ops,
};
int cx18_av_probe(struct cx18 *cx)
{
struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *fmt = &format.format;
/* fix videodecoder resolution */
- fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
- fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
+ fmt->width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+ fmt->height = cxhdl->height;
+ fmt->code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format);
return 0;
}
{
int i;
- for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
+ for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS - 1; i++)
if (cx->card->video_inputs[i].video_type == 0)
break;
cx->nof_inputs = i;
- for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
+ for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS - 1; i++)
if (cx->card->audio_inputs[i].audio_type == 0)
break;
cx->nof_audio_inputs = i;
{
struct cx18_open_id *id = fh2id(fh);
struct cx18 *cx = id->cx;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
struct cx18_stream *s = &cx->streams[id->type];
int ret;
int w, h;
s->vb_bytes_per_line = 1440; /* Packed */
}
- mbus_fmt.width = cx->cxhdl.width = w;
- mbus_fmt.height = cx->cxhdl.height = h;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
+ format.format.width = cx->cxhdl.width = w;
+ format.format.height = cx->cxhdl.height = h;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(cx->sd_av, pad, set_fmt, NULL, &format);
return cx18_g_fmt_vid_cap(file, fh, fmt);
}
"encoder PCM audio",
VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
PCI_DMA_FROMDEVICE,
+ V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
},
{ /* CX18_ENC_STREAM_TYPE_IDX */
"encoder IDX",
if (0 != ret)
goto err;
- inter->state[ci_nr - 1] = state;
+ inter->state[ci_nr - 1] = state;
altera_hw_filt_init(config, ci_nr);
struct v4l2_format *f)
{
struct cx23885_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int err;
dprintk(2, "%s()\n", __func__);
dev->field = f->fmt.pix.field;
dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
dev->width, dev->height, dev->field);
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- call_all(dev, video, s_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
- /* s_mbus_fmt overwrites f->fmt.pix.field, restore it */
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ call_all(dev, pad, set_fmt, NULL, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
+ /* set_fmt overwrites f->fmt.pix.field, restore it */
f->fmt.pix.field = dev->field;
return 0;
}
buf = list_entry(q->active.next,
struct cx88_buffer, list);
v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ buf->vb.v4l2_buf.field = core->field;
+ buf->vb.v4l2_buf.sequence = q->count++;
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
}
/* reset counter */
cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
- q->count = 1;
+ q->count = 0;
/* enable irqs */
dprintk( 1, "setting the interrupt mask\n" );
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.v4l2_buf.index);
cx8802_start_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
return 0;
}
if (list_empty(&cx88q->active)) {
dprintk( 1, "queue is empty - first active\n" );
list_add_tail(&buf->list, &cx88q->active);
- buf->count = cx88q->count++;
dprintk(1,"[%p/%d] %s - first active\n",
buf, buf->vb.v4l2_buf.index, __func__);
dprintk( 1, "queue is not empty - append to active\n" );
prev = list_entry(cx88q->active.prev, struct cx88_buffer, list);
list_add_tail(&buf->list, &cx88q->active);
- buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.v4l2_buf.index, __func__);
/* reset counter */
cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
- q->count = 1;
+ q->count = 0;
/* enable irqs */
cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.v4l2_buf.index);
cx8800_start_vbi_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
return 0;
}
if (list_empty(&q->active)) {
list_add_tail(&buf->list, &q->active);
cx8800_start_vbi_dma(dev, q, buf);
- buf->count = q->count++;
dprintk(2,"[%p/%d] vbi_queue - first active\n",
buf, buf->vb.v4l2_buf.index);
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(q->active.prev, struct cx88_buffer, list);
list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
buf, buf->vb.v4l2_buf.index);
/* reset counter */
cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
- q->count = 1;
+ q->count = 0;
/* enable irqs */
cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
buf, buf->vb.v4l2_buf.index);
start_video_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
- buf->count = q->count++;
}
return 0;
}
if (list_empty(&q->active)) {
list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
dprintk(2,"[%p/%d] buffer_queue - first active\n",
buf, buf->vb.v4l2_buf.index);
buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
prev = list_entry(q->active.prev, struct cx88_buffer, list);
list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2, "[%p/%d] buffer_queue - append to active\n",
buf, buf->vb.v4l2_buf.index);
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
}
/* cx88 specific */
unsigned int bpl;
struct cx88_riscmem risc;
- u32 count;
};
struct cx88_dmaqueue {
--- /dev/null
+config VIDEO_DT3155
+ tristate "DT3155 frame grabber"
+ depends on PCI && VIDEO_DEV && VIDEO_V4L2
+ depends on HAS_DMA
+ select VIDEOBUF2_DMA_CONTIG
+ default n
+ ---help---
+ Enables dt3155 device driver for the DataTranslation DT3155 frame grabber.
+ Say Y here if you have this hardware.
+ In doubt, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called dt3155.
--- /dev/null
+obj-$(CONFIG_VIDEO_DT3155) += dt3155.o
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2006-2010 by Marin Mitov *
+ * mitov@issp.bas.bg *
+ * *
+ * 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 *
+ * (at your option) 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. *
+ * *
+ ***************************************************************************/
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "dt3155.h"
+
+#define DT3155_DEVICE_ID 0x1223
+
+/**
+ * read_i2c_reg - reads an internal i2c register
+ *
+ * @addr: dt3155 mmio base address
+ * @index: index (internal address) of register to read
+ * @data: pointer to byte the read data will be placed in
+ *
+ * returns: zero on success or error code
+ *
+ * This function starts reading the specified (by index) register
+ * and busy waits for the process to finish. The result is placed
+ * in a byte pointed by data.
+ */
+static int read_i2c_reg(void __iomem *addr, u8 index, u8 *data)
+{
+ u32 tmp = index;
+
+ iowrite32((tmp << 17) | IIC_READ, addr + IIC_CSR2);
+ mmiowb();
+ udelay(45); /* wait at least 43 usec for NEW_CYCLE to clear */
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ return -EIO; /* error: NEW_CYCLE not cleared */
+ tmp = ioread32(addr + IIC_CSR1);
+ if (tmp & DIRECT_ABORT) {
+ /* reset DIRECT_ABORT bit */
+ iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
+ return -EIO; /* error: DIRECT_ABORT set */
+ }
+ *data = tmp >> 24;
+ return 0;
+}
+
+/**
+ * write_i2c_reg - writes to an internal i2c register
+ *
+ * @addr: dt3155 mmio base address
+ * @index: index (internal address) of register to read
+ * @data: data to be written
+ *
+ * returns: zero on success or error code
+ *
+ * This function starts writing the specified (by index) register
+ * and busy waits for the process to finish.
+ */
+static int write_i2c_reg(void __iomem *addr, u8 index, u8 data)
+{
+ u32 tmp = index;
+
+ iowrite32((tmp << 17) | IIC_WRITE | data, addr + IIC_CSR2);
+ mmiowb();
+ udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ return -EIO; /* error: NEW_CYCLE not cleared */
+ if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
+ /* reset DIRECT_ABORT bit */
+ iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
+ return -EIO; /* error: DIRECT_ABORT set */
+ }
+ return 0;
+}
+
+/**
+ * write_i2c_reg_nowait - writes to an internal i2c register
+ *
+ * @addr: dt3155 mmio base address
+ * @index: index (internal address) of register to read
+ * @data: data to be written
+ *
+ * This function starts writing the specified (by index) register
+ * and then returns.
+ */
+static void write_i2c_reg_nowait(void __iomem *addr, u8 index, u8 data)
+{
+ u32 tmp = index;
+
+ iowrite32((tmp << 17) | IIC_WRITE | data, addr + IIC_CSR2);
+ mmiowb();
+}
+
+/**
+ * wait_i2c_reg - waits the read/write to finish
+ *
+ * @addr: dt3155 mmio base address
+ *
+ * returns: zero on success or error code
+ *
+ * This function waits reading/writing to finish.
+ */
+static int wait_i2c_reg(void __iomem *addr)
+{
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
+ if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
+ return -EIO; /* error: NEW_CYCLE not cleared */
+ if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
+ /* reset DIRECT_ABORT bit */
+ iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
+ return -EIO; /* error: DIRECT_ABORT set */
+ }
+ return 0;
+}
+
+static int
+dt3155_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *num_planes,
+ unsigned int sizes[], void *alloc_ctxs[])
+
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(vq);
+ unsigned size = pd->width * pd->height;
+
+ if (vq->num_buffers + *nbuffers < 2)
+ *nbuffers = 2 - vq->num_buffers;
+ if (fmt && fmt->fmt.pix.sizeimage < size)
+ return -EINVAL;
+ *num_planes = 1;
+ sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size;
+ alloc_ctxs[0] = pd->alloc_ctx;
+ return 0;
+}
+
+static int dt3155_buf_prepare(struct vb2_buffer *vb)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
+
+ vb2_set_plane_payload(vb, 0, pd->width * pd->height);
+ return 0;
+}
+
+static int dt3155_start_streaming(struct vb2_queue *q, unsigned count)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(q);
+ struct vb2_buffer *vb = pd->curr_buf;
+ dma_addr_t dma_addr;
+
+ pd->sequence = 0;
+ dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ iowrite32(dma_addr, pd->regs + EVEN_DMA_START);
+ iowrite32(dma_addr + pd->width, pd->regs + ODD_DMA_START);
+ iowrite32(pd->width, pd->regs + EVEN_DMA_STRIDE);
+ iowrite32(pd->width, pd->regs + ODD_DMA_STRIDE);
+ /* enable interrupts, clear all irq flags */
+ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
+ FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
+ iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD,
+ pd->regs + CSR1);
+ wait_i2c_reg(pd->regs);
+ write_i2c_reg(pd->regs, CONFIG, pd->config);
+ write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);
+ write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);
+
+ /* start the board */
+ write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | BUSY_ODD);
+ return 0;
+}
+
+static void dt3155_stop_streaming(struct vb2_queue *q)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(q);
+ struct vb2_buffer *vb;
+
+ spin_lock_irq(&pd->lock);
+ /* stop the board */
+ write_i2c_reg_nowait(pd->regs, CSR2, pd->csr2);
+ iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN, pd->regs + CSR1);
+ /* disable interrupts, clear all irq flags */
+ iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
+ spin_unlock_irq(&pd->lock);
+
+ /*
+ * It is not clear whether the DMA stops at once or whether it
+ * will finish the current frame or field first. To be on the
+ * safe side we wait a bit.
+ */
+ msleep(45);
+
+ spin_lock_irq(&pd->lock);
+ if (pd->curr_buf) {
+ vb2_buffer_done(pd->curr_buf, VB2_BUF_STATE_ERROR);
+ pd->curr_buf = NULL;
+ }
+
+ while (!list_empty(&pd->dmaq)) {
+ vb = list_first_entry(&pd->dmaq, typeof(*vb), done_entry);
+ list_del(&vb->done_entry);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irq(&pd->lock);
+}
+
+static void dt3155_buf_queue(struct vb2_buffer *vb)
+{
+ struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
+
+ /* pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked */
+ spin_lock_irq(&pd->lock);
+ if (pd->curr_buf)
+ list_add_tail(&vb->done_entry, &pd->dmaq);
+ else
+ pd->curr_buf = vb;
+ spin_unlock_irq(&pd->lock);
+}
+
+static const struct vb2_ops q_ops = {
+ .queue_setup = dt3155_queue_setup,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .buf_prepare = dt3155_buf_prepare,
+ .start_streaming = dt3155_start_streaming,
+ .stop_streaming = dt3155_stop_streaming,
+ .buf_queue = dt3155_buf_queue,
+};
+
+static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id)
+{
+ struct dt3155_priv *ipd = dev_id;
+ struct vb2_buffer *ivb;
+ dma_addr_t dma_addr;
+ u32 tmp;
+
+ tmp = ioread32(ipd->regs + INT_CSR) & (FLD_START | FLD_END_ODD);
+ if (!tmp)
+ return IRQ_NONE; /* not our irq */
+ if ((tmp & FLD_START) && !(tmp & FLD_END_ODD)) {
+ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START,
+ ipd->regs + INT_CSR);
+ return IRQ_HANDLED; /* start of field irq */
+ }
+ tmp = ioread32(ipd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD);
+ if (tmp) {
+ iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN |
+ CAP_CONT_EVEN | CAP_CONT_ODD,
+ ipd->regs + CSR1);
+ mmiowb();
+ }
+
+ spin_lock(&ipd->lock);
+ if (ipd->curr_buf && !list_empty(&ipd->dmaq)) {
+ v4l2_get_timestamp(&ipd->curr_buf->v4l2_buf.timestamp);
+ ipd->curr_buf->v4l2_buf.sequence = ipd->sequence++;
+ ipd->curr_buf->v4l2_buf.field = V4L2_FIELD_NONE;
+ vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
+
+ ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
+ list_del(&ivb->done_entry);
+ ipd->curr_buf = ivb;
+ dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
+ iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
+ iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START);
+ iowrite32(ipd->width, ipd->regs + EVEN_DMA_STRIDE);
+ iowrite32(ipd->width, ipd->regs + ODD_DMA_STRIDE);
+ mmiowb();
+ }
+
+ /* enable interrupts, clear all irq flags */
+ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
+ FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
+ spin_unlock(&ipd->lock);
+ return IRQ_HANDLED;
+}
+
+static const struct v4l2_file_operations dt3155_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .unlocked_ioctl = video_ioctl2,
+ .read = vb2_fop_read,
+ .mmap = vb2_fop_mmap,
+ .poll = vb2_fop_poll
+};
+
+static int dt3155_querycap(struct file *filp, void *p,
+ struct v4l2_capability *cap)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ strcpy(cap->driver, DT3155_NAME);
+ strcpy(cap->card, DT3155_NAME " frame grabber");
+ sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int dt3155_enum_fmt_vid_cap(struct file *filp,
+ void *p, struct v4l2_fmtdesc *f)
+{
+ if (f->index)
+ return -EINVAL;
+ f->pixelformat = V4L2_PIX_FMT_GREY;
+ strcpy(f->description, "8-bit Greyscale");
+ return 0;
+}
+
+static int dt3155_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ f->fmt.pix.width = pd->width;
+ f->fmt.pix.height = pd->height;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.bytesperline = f->fmt.pix.width;
+ f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return 0;
+}
+
+static int dt3155_g_std(struct file *filp, void *p, v4l2_std_id *norm)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ *norm = pd->std;
+ return 0;
+}
+
+static int dt3155_s_std(struct file *filp, void *p, v4l2_std_id norm)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ if (pd->std == norm)
+ return 0;
+ if (vb2_is_busy(&pd->vidq))
+ return -EBUSY;
+ pd->std = norm;
+ if (pd->std & V4L2_STD_525_60) {
+ pd->csr2 = VT_60HZ;
+ pd->width = 640;
+ pd->height = 480;
+ } else {
+ pd->csr2 = VT_50HZ;
+ pd->width = 768;
+ pd->height = 576;
+ }
+ return 0;
+}
+
+static int dt3155_enum_input(struct file *filp, void *p,
+ struct v4l2_input *input)
+{
+ if (input->index > 3)
+ return -EINVAL;
+ if (input->index)
+ snprintf(input->name, sizeof(input->name), "VID%d",
+ input->index);
+ else
+ strlcpy(input->name, "J2/VID0", sizeof(input->name));
+ input->type = V4L2_INPUT_TYPE_CAMERA;
+ input->std = V4L2_STD_ALL;
+ input->status = 0;
+ return 0;
+}
+
+static int dt3155_g_input(struct file *filp, void *p, unsigned int *i)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ *i = pd->input;
+ return 0;
+}
+
+static int dt3155_s_input(struct file *filp, void *p, unsigned int i)
+{
+ struct dt3155_priv *pd = video_drvdata(filp);
+
+ if (i > 3)
+ return -EINVAL;
+ pd->input = i;
+ write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
+ write_i2c_reg(pd->regs, AD_CMD, (i << 6) | (i << 4) | SYNC_LVL_3);
+ return 0;
+}
+
+static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
+ .vidioc_querycap = dt3155_querycap,
+ .vidioc_enum_fmt_vid_cap = dt3155_enum_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = dt3155_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = dt3155_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = dt3155_fmt_vid_cap,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_g_std = dt3155_g_std,
+ .vidioc_s_std = dt3155_s_std,
+ .vidioc_enum_input = dt3155_enum_input,
+ .vidioc_g_input = dt3155_g_input,
+ .vidioc_s_input = dt3155_s_input,
+};
+
+static int dt3155_init_board(struct dt3155_priv *pd)
+{
+ struct pci_dev *pdev = pd->pdev;
+ int i;
+ u8 tmp = 0;
+
+ pci_set_master(pdev); /* dt3155 needs it */
+
+ /* resetting the adapter */
+ iowrite32(ADDR_ERR_ODD | ADDR_ERR_EVEN | FLD_CRPT_ODD | FLD_CRPT_EVEN |
+ FLD_DN_ODD | FLD_DN_EVEN, pd->regs + CSR1);
+ mmiowb();
+ msleep(20);
+
+ /* initializing adapter registers */
+ iowrite32(FIFO_EN | SRST, pd->regs + CSR1);
+ mmiowb();
+ iowrite32(0xEEEEEE01, pd->regs + EVEN_PIXEL_FMT);
+ iowrite32(0xEEEEEE01, pd->regs + ODD_PIXEL_FMT);
+ iowrite32(0x00000020, pd->regs + FIFO_TRIGER);
+ iowrite32(0x00000103, pd->regs + XFER_MODE);
+ iowrite32(0, pd->regs + RETRY_WAIT_CNT);
+ iowrite32(0, pd->regs + INT_CSR);
+ iowrite32(1, pd->regs + EVEN_FLD_MASK);
+ iowrite32(1, pd->regs + ODD_FLD_MASK);
+ iowrite32(0, pd->regs + MASK_LENGTH);
+ iowrite32(0x0005007C, pd->regs + FIFO_FLAG_CNT);
+ iowrite32(0x01010101, pd->regs + IIC_CLK_DUR);
+ mmiowb();
+
+ /* verifying that we have a DT3155 board (not just a SAA7116 chip) */
+ read_i2c_reg(pd->regs, DT_ID, &tmp);
+ if (tmp != DT3155_ID)
+ return -ENODEV;
+
+ /* initialize AD LUT */
+ write_i2c_reg(pd->regs, AD_ADDR, 0);
+ for (i = 0; i < 256; i++)
+ write_i2c_reg(pd->regs, AD_LUT, i);
+
+ /* initialize ADC references */
+ /* FIXME: pos_ref & neg_ref depend on VT_50HZ */
+ write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
+ write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
+ write_i2c_reg(pd->regs, AD_ADDR, AD_POS_REF);
+ write_i2c_reg(pd->regs, AD_CMD, 34);
+ write_i2c_reg(pd->regs, AD_ADDR, AD_NEG_REF);
+ write_i2c_reg(pd->regs, AD_CMD, 0);
+
+ /* initialize PM LUT */
+ write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM);
+ for (i = 0; i < 256; i++) {
+ write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
+ write_i2c_reg(pd->regs, PM_LUT_DATA, i);
+ }
+ write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM | PM_LUT_SEL);
+ for (i = 0; i < 256; i++) {
+ write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
+ write_i2c_reg(pd->regs, PM_LUT_DATA, i);
+ }
+ write_i2c_reg(pd->regs, CONFIG, pd->config); /* ACQ_MODE_EVEN */
+
+ /* select channel 1 for input and set sync level */
+ write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
+ write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
+
+ /* disable all irqs, clear all irq flags */
+ iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
+ pd->regs + INT_CSR);
+
+ return 0;
+}
+
+static struct video_device dt3155_vdev = {
+ .name = DT3155_NAME,
+ .fops = &dt3155_fops,
+ .ioctl_ops = &dt3155_ioctl_ops,
+ .minor = -1,
+ .release = video_device_release_empty,
+ .tvnorms = V4L2_STD_ALL,
+};
+
+static int dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err;
+ struct dt3155_priv *pd;
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return -ENODEV;
+ pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+
+ err = v4l2_device_register(&pdev->dev, &pd->v4l2_dev);
+ if (err)
+ return err;
+ pd->vdev = dt3155_vdev;
+ pd->vdev.v4l2_dev = &pd->v4l2_dev;
+ video_set_drvdata(&pd->vdev, pd); /* for use in video_fops */
+ pd->pdev = pdev;
+ pd->std = V4L2_STD_625_50;
+ pd->csr2 = VT_50HZ;
+ pd->width = 768;
+ pd->height = 576;
+ INIT_LIST_HEAD(&pd->dmaq);
+ mutex_init(&pd->mux);
+ pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */
+ pd->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ pd->vidq.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ pd->vidq.io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
+ pd->vidq.ops = &q_ops;
+ pd->vidq.mem_ops = &vb2_dma_contig_memops;
+ pd->vidq.drv_priv = pd;
+ pd->vidq.min_buffers_needed = 2;
+ pd->vidq.gfp_flags = GFP_DMA32;
+ pd->vidq.lock = &pd->mux; /* for locking v4l2_file_operations */
+ pd->vdev.queue = &pd->vidq;
+ err = vb2_queue_init(&pd->vidq);
+ if (err < 0)
+ goto err_v4l2_dev_unreg;
+ pd->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ if (IS_ERR(pd->alloc_ctx)) {
+ dev_err(&pdev->dev, "Can't allocate buffer context");
+ err = PTR_ERR(pd->alloc_ctx);
+ goto err_v4l2_dev_unreg;
+ }
+ spin_lock_init(&pd->lock);
+ pd->config = ACQ_MODE_EVEN;
+ err = pci_enable_device(pdev);
+ if (err)
+ goto err_free_ctx;
+ err = pci_request_region(pdev, 0, pci_name(pdev));
+ if (err)
+ goto err_pci_disable;
+ pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
+ if (!pd->regs) {
+ err = -ENOMEM;
+ goto err_free_reg;
+ }
+ err = dt3155_init_board(pd);
+ if (err)
+ goto err_iounmap;
+ err = request_irq(pd->pdev->irq, dt3155_irq_handler_even,
+ IRQF_SHARED, DT3155_NAME, pd);
+ if (err)
+ goto err_iounmap;
+ err = video_register_device(&pd->vdev, VFL_TYPE_GRABBER, -1);
+ if (err)
+ goto err_free_irq;
+ dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev.minor);
+ return 0; /* success */
+
+err_free_irq:
+ free_irq(pd->pdev->irq, pd);
+err_iounmap:
+ pci_iounmap(pdev, pd->regs);
+err_free_reg:
+ pci_release_region(pdev, 0);
+err_pci_disable:
+ pci_disable_device(pdev);
+err_free_ctx:
+ vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
+err_v4l2_dev_unreg:
+ v4l2_device_unregister(&pd->v4l2_dev);
+ return err;
+}
+
+static void dt3155_remove(struct pci_dev *pdev)
+{
+ struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
+ struct dt3155_priv *pd = container_of(v4l2_dev, struct dt3155_priv,
+ v4l2_dev);
+
+ video_unregister_device(&pd->vdev);
+ free_irq(pd->pdev->irq, pd);
+ vb2_queue_release(&pd->vidq);
+ v4l2_device_unregister(&pd->v4l2_dev);
+ pci_iounmap(pdev, pd->regs);
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ vb2_dma_contig_cleanup_ctx(pd->alloc_ctx);
+}
+
+static const struct pci_device_id pci_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, DT3155_DEVICE_ID) },
+ { 0, /* zero marks the end */ },
+};
+MODULE_DEVICE_TABLE(pci, pci_ids);
+
+static struct pci_driver pci_driver = {
+ .name = DT3155_NAME,
+ .id_table = pci_ids,
+ .probe = dt3155_probe,
+ .remove = dt3155_remove,
+};
+
+module_pci_driver(pci_driver);
+
+MODULE_DESCRIPTION("video4linux pci-driver for dt3155 frame grabber");
+MODULE_AUTHOR("Marin Mitov <mitov@issp.bas.bg>");
+MODULE_VERSION(DT3155_VERSION);
+MODULE_LICENSE("GPL");
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2006-2010 by Marin Mitov *
+ * mitov@issp.bas.bg *
+ * *
+ * 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 *
+ * (at your option) 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. *
+ * *
+ ***************************************************************************/
+
+/* DT3155 header file */
+#ifndef _DT3155_H_
+#define _DT3155_H_
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dev.h>
+
+#define DT3155_NAME "dt3155"
+#define DT3155_VER_MAJ 2
+#define DT3155_VER_MIN 0
+#define DT3155_VER_EXT 0
+#define DT3155_VERSION __stringify(DT3155_VER_MAJ) "." \
+ __stringify(DT3155_VER_MIN) "." \
+ __stringify(DT3155_VER_EXT)
+
+/* DT3155 Base Register offsets (memory mapped) */
+#define EVEN_DMA_START 0x00
+#define ODD_DMA_START 0x0C
+#define EVEN_DMA_STRIDE 0x18
+#define ODD_DMA_STRIDE 0x24
+#define EVEN_PIXEL_FMT 0x30
+#define ODD_PIXEL_FMT 0x34
+#define FIFO_TRIGER 0x38
+#define XFER_MODE 0x3C
+#define CSR1 0x40
+#define RETRY_WAIT_CNT 0x44
+#define INT_CSR 0x48
+#define EVEN_FLD_MASK 0x4C
+#define ODD_FLD_MASK 0x50
+#define MASK_LENGTH 0x54
+#define FIFO_FLAG_CNT 0x58
+#define IIC_CLK_DUR 0x5C
+#define IIC_CSR1 0x60
+#define IIC_CSR2 0x64
+
+/* DT3155 Internal Registers indexes (i2c/IIC mapped) */
+#define CSR2 0x10
+#define EVEN_CSR 0x11
+#define ODD_CSR 0x12
+#define CONFIG 0x13
+#define DT_ID 0x1F
+#define X_CLIP_START 0x20
+#define Y_CLIP_START 0x22
+#define X_CLIP_END 0x24
+#define Y_CLIP_END 0x26
+#define AD_ADDR 0x30
+#define AD_LUT 0x31
+#define AD_CMD 0x32
+#define DIG_OUT 0x40
+#define PM_LUT_ADDR 0x50
+#define PM_LUT_DATA 0x51
+
+/* AD command register values */
+#define AD_CMD_REG 0x00
+#define AD_POS_REF 0x01
+#define AD_NEG_REF 0x02
+
+/* CSR1 bit masks */
+#define RANGE_EN 0x00008000
+#define CRPT_DIS 0x00004000
+#define ADDR_ERR_ODD 0x00000800
+#define ADDR_ERR_EVEN 0x00000400
+#define FLD_CRPT_ODD 0x00000200
+#define FLD_CRPT_EVEN 0x00000100
+#define FIFO_EN 0x00000080
+#define SRST 0x00000040
+#define FLD_DN_ODD 0x00000020
+#define FLD_DN_EVEN 0x00000010
+/* These should not be used.
+ * Use CAP_CONT_ODD/EVEN instead
+#define CAP_SNGL_ODD 0x00000008
+#define CAP_SNGL_EVEN 0x00000004
+*/
+#define CAP_CONT_ODD 0x00000002
+#define CAP_CONT_EVEN 0x00000001
+
+/* INT_CSR bit masks */
+#define FLD_START_EN 0x00000400
+#define FLD_END_ODD_EN 0x00000200
+#define FLD_END_EVEN_EN 0x00000100
+#define FLD_START 0x00000004
+#define FLD_END_ODD 0x00000002
+#define FLD_END_EVEN 0x00000001
+
+/* IIC_CSR1 bit masks */
+#define DIRECT_ABORT 0x00000200
+
+/* IIC_CSR2 bit masks */
+#define NEW_CYCLE 0x01000000
+#define DIR_RD 0x00010000
+#define IIC_READ 0x01010000
+#define IIC_WRITE 0x01000000
+
+/* CSR2 bit masks */
+#define DISP_PASS 0x40
+#define BUSY_ODD 0x20
+#define BUSY_EVEN 0x10
+#define SYNC_PRESENT 0x08
+#define VT_50HZ 0x04
+#define SYNC_SNTL 0x02
+#define CHROM_FILT 0x01
+#define VT_60HZ 0x00
+
+/* CSR_EVEN/ODD bit masks */
+#define CSR_ERROR 0x04
+#define CSR_SNGL 0x02
+#define CSR_DONE 0x01
+
+/* CONFIG bit masks */
+#define PM_LUT_PGM 0x80
+#define PM_LUT_SEL 0x40
+#define CLIP_EN 0x20
+#define HSCALE_EN 0x10
+#define EXT_TRIG_UP 0x0C
+#define EXT_TRIG_DOWN 0x04
+#define ACQ_MODE_NEXT 0x02
+#define ACQ_MODE_ODD 0x01
+#define ACQ_MODE_EVEN 0x00
+
+/* AD_CMD bit masks */
+#define VIDEO_CNL_1 0x00
+#define VIDEO_CNL_2 0x40
+#define VIDEO_CNL_3 0x80
+#define VIDEO_CNL_4 0xC0
+#define SYNC_CNL_1 0x00
+#define SYNC_CNL_2 0x10
+#define SYNC_CNL_3 0x20
+#define SYNC_CNL_4 0x30
+#define SYNC_LVL_1 0x00
+#define SYNC_LVL_2 0x04
+#define SYNC_LVL_3 0x08
+#define SYNC_LVL_4 0x0C
+
+/* DT3155 identificator */
+#define DT3155_ID 0x20
+
+/* per board private data structure */
+/**
+ * struct dt3155_priv - private data structure
+ *
+ * @v4l2_dev: v4l2_device structure
+ * @vdev: video_device structure
+ * @pdev: pointer to pci_dev structure
+ * @vidq: vb2_queue structure
+ * @alloc_ctx: dma_contig allocation context
+ * @curr_buf: pointer to curren buffer
+ * @mux: mutex to protect the instance
+ * @dmaq: queue for dma buffers
+ * @lock: spinlock for dma queue
+ * @std: input standard
+ * @width: frame width
+ * @height: frame height
+ * @input: current input
+ * @sequence: frame counter
+ * @stats: statistics structure
+ * @regs: local copy of mmio base register
+ * @csr2: local copy of csr2 register
+ * @config: local copy of config register
+ */
+struct dt3155_priv {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct pci_dev *pdev;
+ struct vb2_queue vidq;
+ struct vb2_alloc_ctx *alloc_ctx;
+ struct vb2_buffer *curr_buf;
+ struct mutex mux;
+ struct list_head dmaq;
+ spinlock_t lock;
+ v4l2_std_id std;
+ unsigned width, height;
+ unsigned input;
+ unsigned int sequence;
+ void __iomem *regs;
+ u8 csr2, config;
+};
+
+#endif /* _DT3155_H_ */
{
struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
/* fix videodecoder resolution */
- fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
- fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
+ format.format.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+ format.format.height = cxhdl->height;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(itv->sd_video, pad, set_fmt, NULL, &format);
return 0;
}
{
int i;
- for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
+ for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS - 1; i++)
if (itv->card->video_inputs[i].video_type == 0)
break;
itv->nof_inputs = i;
- for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
+ for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS - 1; i++)
if (itv->card->audio_inputs[i].audio_type == 0)
break;
itv->nof_audio_inputs = i;
{
struct ivtv_open_id *id = fh2id(fh);
struct ivtv *itv = id->itv;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
int w = fmt->fmt.pix.width;
int h = fmt->fmt.pix.height;
itv->cxhdl.height = h;
if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
fmt->fmt.pix.width /= 2;
- mbus_fmt.width = fmt->fmt.pix.width;
- mbus_fmt.height = h;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
+ format.format.width = fmt->fmt.pix.width;
+ format.format.height = h;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(itv->sd_video, pad, set_fmt, NULL, &format);
return ivtv_g_fmt_vid_cap(file, fh, fmt);
}
return err;
- dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
- mantis_uart_exit(mantis);
-
fail6:
fail4:
dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
if (chan->fe2) {
if (dvb_register_frontend(adapter, chan->fe2) < 0)
goto err;
- chan->fe2->tuner_priv = chan->fe->tuner_priv;
- memcpy(&chan->fe2->ops.tuner_ops,
- &chan->fe->ops.tuner_ops,
- sizeof(struct dvb_tuner_ops));
+ if (chan->fe) {
+ chan->fe2->tuner_priv = chan->fe->tuner_priv;
+ memcpy(&chan->fe2->ops.tuner_ops,
+ &chan->fe->ops.tuner_ops,
+ sizeof(struct dvb_tuner_ops));
+ }
}
if (chan->has_demux) {
saa7134_set_gpio(dev, 20, 1);
break;
}
- return 0;
+ return 0;
}
return -EINVAL;
}
break;
case 0x001d:
dev->tuner_type = TUNER_PHILIPS_FMD1216ME_MK3;
- printk(KERN_INFO "%s Board has DVB-T\n", dev->name);
+ printk(KERN_INFO "%s Board has DVB-T\n",
+ dev->name);
break;
default:
printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
case SAA7134_BOARD_ASUSTeK_TVFM7135:
/* The card below is detected as card=53, but is different */
if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
- dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
- printk(KERN_INFO "%s: P7131 analog only, using "
- "entry of %s\n",
- dev->name, saa7134_boards[dev->board].name);
+ dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
+ printk(KERN_INFO
+ "%s: P7131 analog only, using entry of %s\n",
+ dev->name, saa7134_boards[dev->board].name);
- /* IR init has already happened for other cards, so
- * we have to catch up. */
+ /*
+ * IR init has already happened for other cards, so
+ * we have to catch up.
+ */
dev->has_remote = SAA7134_REMOTE_GPIO;
saa7134_input_init1(dev);
}
&dev->i2c_adap, 0, 0) == NULL) {
wprintk("%s: Asus Tiger 3in1, no lnbp21"
" found!\n", __func__);
- goto detach_frontend;
+ goto detach_frontend;
}
}
}
struct v4l2_format *f)
{
struct saa7134_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
- saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
+ saa_call_all(dev, pad, get_fmt, NULL, &fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ v4l2_fill_pix_format(&f->fmt.pix, mbus_fmt);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
struct v4l2_format *f)
{
struct saa7134_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ saa_call_all(dev, pad, set_fmt, NULL, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
struct v4l2_format *f)
{
struct saa7134_dev *dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
-
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ saa_call_all(dev, pad, set_fmt, &pad_cfg, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
u8 buf[256];
int ret;
- dprintk(DBGLVL_API, "%s()\n", __func__);
+ dprintk(DBGLVL_API, "%s() addr=%x reglen=%d datalen=%d\n",
+ __func__, addr, reglen, datalen);
if (reglen > 4)
return -EIO;
* 08... register address
*/
memset(buf, 0, sizeof(buf));
- memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);
+ if (reg)
+ memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);
*((u32 *)(buf + 0 * sizeof(u32))) = reglen;
*((u32 *)(buf + 1 * sizeof(u32))) = datalen;
u8 buf[256];
int ret;
- dprintk(DBGLVL_API, "%s()\n", __func__);
+ dprintk(DBGLVL_API, "%s() addr=0x%2x len=0x%x\n",
+ __func__, addr, datalen);
if ((datalen == 0) || (datalen > 232))
return -EIO;
return -EIO;
}
- dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
+ dprintk(DBGLVL_API, "%s() len = %d bytes unitid=0x%x\n", __func__,
+ len, unitid);
/* Prepare the send buffer */
/* Bytes 00-03 dest register length
* 04-07 dest bytes to write
* 08... register address
*/
+ if (datalen == 1) {
+ /* Workaround for issues with i2c components
+ * that issue writes with no data. IE: SI2168/2157
+ * Increase reglen by 1, strobe out an additional byte,
+ * ignored by SI2168/2157.
+ */
+ datalen++;
+ }
*((u32 *)(buf + 0 * sizeof(u32))) = reglen;
*((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen;
memcpy((buf + 2 * sizeof(u32)), data, datalen);
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
* attached I2C devices, so we can simplify the virtual i2c mechansms
* and keep the -i2c.c implementation clean.
*/
+#define REGLEN_0bit 0
#define REGLEN_8bit 1
#define REGLEN_16bit 2
.i2c_reg_len = REGLEN_8bit,
} },
},
+ [SAA7164_BOARD_HAUPPAUGE_HVR2255proto] = {
+ .name = "Hauppauge WinTV-HVR2255(proto)",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x27,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x06,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xb2 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x24,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x26,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x1c >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
+ [SAA7164_BOARD_HAUPPAUGE_HVR2255] = {
+ .name = "Hauppauge WinTV-HVR2255",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x28,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x06,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xb2 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x25,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x27,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "LGDT3306-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0x1c >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
+ [SAA7164_BOARD_HAUPPAUGE_HVR2205] = {
+ .name = "Hauppauge WinTV-HVR2205",
+ .porta = SAA7164_MPEG_DVB,
+ .portb = SAA7164_MPEG_DVB,
+ .portc = SAA7164_MPEG_ENCODER,
+ .portd = SAA7164_MPEG_ENCODER,
+ .porte = SAA7164_MPEG_VBI,
+ .portf = SAA7164_MPEG_VBI,
+ .chiprev = SAA7164_CHIP_REV3,
+ .unit = {{
+ .id = 0x28,
+ .type = SAA7164_UNIT_EEPROM,
+ .name = "4K EEPROM",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xa0 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x04,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_0,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x06,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "SI2168-1",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xc8 >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ }, {
+ .id = 0x25,
+ .type = SAA7164_UNIT_TUNER,
+ .name = "SI2157-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_1,
+ .i2c_bus_addr = 0xc0 >> 1,
+ .i2c_reg_len = REGLEN_0bit,
+ }, {
+ .id = 0x27,
+ .type = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+ .name = "SI2168-2",
+ .i2c_bus_nr = SAA7164_I2C_BUS_2,
+ .i2c_bus_addr = 0xcc >> 1,
+ .i2c_reg_len = REGLEN_8bit,
+ } },
+ },
};
const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
.subvendor = 0x0070,
.subdevice = 0x8953,
.card = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0xf111,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255,
+ /* Prototype card left here for documenation purposes.
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2255proto,
+ */
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0xf123,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0xf120,
+ .card = SAA7164_BOARD_HAUPPAUGE_HVR2205,
},
};
const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2205:
/*
+ HVR2200 / HVR2250
GPIO 2: s5h1411 / tda10048-1 demod reset
GPIO 3: s5h1411 / tda10048-2 demod reset
GPIO 7: IRBlaster Zilog reset
*/
+ /* HVR2255
+ * GPIO 2: lgdg3306-1 demod reset
+ * GPIO 3: lgdt3306-2 demod reset
+ */
+
+ /* HVR2205
+ * GPIO 2: si2168-1 demod reset
+ * GPIO 3: si2168-2 demod reset
+ */
+
/* Reset parts by going in and out of reset */
saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
/* WinTV-HVR2200 (PCIe, Retail, half-height)
* DVB-T (TDA18271/TDA10048) and basic analog, no IR */
break;
+ case 151009:
+ /* First production board rev B2I6 */
+ /* WinTV-HVR2205 (PCIe, Retail, full-height bracket)
+ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */
+ break;
+ case 151609:
+ /* First production board rev B2I6 */
+ /* WinTV-HVR2205 (PCIe, Retail, half-height bracket)
+ * DVB-T/T2/C (SI2157/SI2168) and basic analog, FM */
+ break;
+ case 151061:
+ /* First production board rev B1I6 */
+ /* WinTV-HVR2255 (PCIe, Retail, full-height bracket)
+ * ATSC/QAM (SI2157/LGDT3306) and basic analog, FM */
+ break;
default:
printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
dev->name, tv.model);
case SAA7164_BOARD_HAUPPAUGE_HVR2250:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2205:
hauppauge_eeprom(dev, &eeprom[0]);
break;
}
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
static irqreturn_t saa7164_irq(int irq, void *dev_id)
{
struct saa7164_dev *dev = dev_id;
- struct saa7164_port *porta = &dev->ports[SAA7164_PORT_TS1];
- struct saa7164_port *portb = &dev->ports[SAA7164_PORT_TS2];
- struct saa7164_port *portc = &dev->ports[SAA7164_PORT_ENC1];
- struct saa7164_port *portd = &dev->ports[SAA7164_PORT_ENC2];
- struct saa7164_port *porte = &dev->ports[SAA7164_PORT_VBI1];
- struct saa7164_port *portf = &dev->ports[SAA7164_PORT_VBI2];
+ struct saa7164_port *porta, *portb, *portc, *portd, *porte, *portf;
u32 intid, intstat[INT_SIZE/4];
int i, handled = 0, bit;
goto out;
}
+ porta = &dev->ports[SAA7164_PORT_TS1];
+ portb = &dev->ports[SAA7164_PORT_TS2];
+ portc = &dev->ports[SAA7164_PORT_ENC1];
+ portd = &dev->ports[SAA7164_PORT_ENC2];
+ porte = &dev->ports[SAA7164_PORT_VBI1];
+ portf = &dev->ports[SAA7164_PORT_VBI2];
+
/* Check that the hardware is accessible. If the status bytes are
* 0xFF then the device is not accessible, the the IRQ belongs
* to another driver.
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
#include "tda10048.h"
#include "tda18271.h"
#include "s5h1411.h"
+#include "si2157.h"
+#include "si2168.h"
+#include "lgdt3306a.h"
#define DRIVER_NAME "saa7164"
.mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
+static struct lgdt3306a_config hauppauge_hvr2255a_config = {
+ .i2c_addr = 0xb2 >> 1,
+ .qam_if_khz = 4000,
+ .vsb_if_khz = 3250,
+ .deny_i2c_rptr = 1, /* Disabled */
+ .spectral_inversion = 0, /* Disabled */
+ .mpeg_mode = LGDT3306A_MPEG_SERIAL,
+ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE,
+ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH,
+ .xtalMHz = 25, /* 24 or 25 */
+};
+
+static struct lgdt3306a_config hauppauge_hvr2255b_config = {
+ .i2c_addr = 0x1c >> 1,
+ .qam_if_khz = 4000,
+ .vsb_if_khz = 3250,
+ .deny_i2c_rptr = 1, /* Disabled */
+ .spectral_inversion = 0, /* Disabled */
+ .mpeg_mode = LGDT3306A_MPEG_SERIAL,
+ .tpclk_edge = LGDT3306A_TPCLK_RISING_EDGE,
+ .tpvalid_polarity = LGDT3306A_TP_VALID_HIGH,
+ .xtalMHz = 25, /* 24 or 25 */
+};
+
+static struct si2157_config hauppauge_hvr2255_tuner_config = {
+ .inversion = 1,
+};
+
+static int si2157_attach(struct saa7164_port *port, struct i2c_adapter *adapter,
+ struct dvb_frontend *fe, u8 addr8bit, struct si2157_config *cfg)
+{
+ struct i2c_board_info bi;
+ struct i2c_client *tuner;
+
+ cfg->fe = fe;
+
+ memset(&bi, 0, sizeof(bi));
+
+ strlcpy(bi.type, "si2157", I2C_NAME_SIZE);
+ bi.platform_data = cfg;
+ bi.addr = addr8bit >> 1;
+
+ request_module(bi.type);
+
+ tuner = i2c_new_device(adapter, &bi);
+ if (tuner == NULL || tuner->dev.driver == NULL)
+ return -ENODEV;
+
+ if (!try_module_get(tuner->dev.driver->owner)) {
+ i2c_unregister_device(tuner);
+ return -ENODEV;
+ }
+
+ port->i2c_client_tuner = tuner;
+
+ return 0;
+}
+
static int saa7164_dvb_stop_port(struct saa7164_port *port)
{
struct saa7164_dev *dev = port->dev;
if (!demux->dmx.frontend)
return -EINVAL;
- mutex_lock(&dvb->lock);
- if (dvb->feeding++ == 0) {
- /* Start transport */
- ret = saa7164_dvb_start_port(port);
+ if (dvb) {
+ mutex_lock(&dvb->lock);
+ if (dvb->feeding++ == 0) {
+ /* Start transport */
+ ret = saa7164_dvb_start_port(port);
+ }
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
}
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
return ret;
}
dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
- mutex_lock(&dvb->lock);
- if (--dvb->feeding == 0) {
- /* Stop transport */
- ret = saa7164_dvb_stop_streaming(port);
+ if (dvb) {
+ mutex_lock(&dvb->lock);
+ if (--dvb->feeding == 0) {
+ /* Stop transport */
+ ret = saa7164_dvb_stop_streaming(port);
+ }
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
}
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
return ret;
}
struct saa7164_dev *dev = port->dev;
struct saa7164_buffer *b;
struct list_head *c, *n;
+ struct i2c_client *client;
dprintk(DBGLVL_DVB, "%s()\n", __func__);
if (dvb->frontend == NULL)
return 0;
+ /* remove I2C client for tuner */
+ client = port->i2c_client_tuner;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ /* remove I2C client for demodulator */
+ client = port->i2c_client_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
dvb_net_release(&dvb->net);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
struct saa7164_dev *dev = port->dev;
struct saa7164_dvb *dvb = &port->dvb;
struct saa7164_i2c *i2c_bus = NULL;
+ struct si2168_config si2168_config;
+ struct si2157_config si2157_config;
+ struct i2c_adapter *adapter;
+ struct i2c_board_info info;
+ struct i2c_client *client_demod;
+ struct i2c_client *client_tuner;
int ret;
dprintk(DBGLVL_DVB, "%s()\n", __func__);
}
}
+ break;
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255proto:
+ case SAA7164_BOARD_HAUPPAUGE_HVR2255:
+ i2c_bus = &dev->i2c_bus[2];
+
+ if (port->nr == 0) {
+ port->dvb.frontend = dvb_attach(lgdt3306a_attach,
+ &hauppauge_hvr2255a_config, &i2c_bus->i2c_adap);
+ } else {
+ port->dvb.frontend = dvb_attach(lgdt3306a_attach,
+ &hauppauge_hvr2255b_config, &i2c_bus->i2c_adap);
+ }
+
+ if (port->dvb.frontend != NULL) {
+
+ if (port->nr == 0) {
+ si2157_attach(port, &dev->i2c_bus[0].i2c_adap,
+ port->dvb.frontend, 0xc0,
+ &hauppauge_hvr2255_tuner_config);
+ } else {
+ si2157_attach(port, &dev->i2c_bus[1].i2c_adap,
+ port->dvb.frontend, 0xc0,
+ &hauppauge_hvr2255_tuner_config);
+ }
+ }
+ break;
+ case SAA7164_BOARD_HAUPPAUGE_HVR2205:
+
+ if (port->nr == 0) {
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &port->dvb.frontend;
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0xc8 >> 1;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap,
+ &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = port->dvb.frontend;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0xc0 >> 1;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client_tuner = i2c_new_device(&dev->i2c_bus[0].i2c_adap,
+ &info);
+ if (!client_tuner || !client_tuner->dev.driver) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_tuner = client_tuner;
+ } else {
+ /* attach frontend */
+ memset(&si2168_config, 0, sizeof(si2168_config));
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &port->dvb.frontend;
+ si2168_config.ts_mode = SI2168_TS_SERIAL;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0xcc >> 1;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&dev->i2c_bus[2].i2c_adap,
+ &info);
+ if (!client_demod || !client_demod->dev.driver)
+ goto frontend_detach;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = port->dvb.frontend;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0xc0 >> 1;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client_tuner = i2c_new_device(&dev->i2c_bus[1].i2c_adap,
+ &info);
+ if (!client_tuner || !client_tuner->dev.driver) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ goto frontend_detach;
+ }
+ port->i2c_client_tuner = client_tuner;
+ }
+
break;
default:
printk(KERN_ERR "%s: The frontend isn't supported\n",
}
return 0;
+
+frontend_detach:
+ printk(KERN_ERR "%s() Frontend/I2C initialization failed\n", __func__);
+ return -1;
}
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->capabilities =
+ cap->device_caps =
V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_READWRITE |
- 0;
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_TUNER;
- cap->capabilities |= V4L2_CAP_TUNER;
- cap->version = 0;
+ cap->capabilities = cap->device_caps |
+ V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_DEVICE_CAPS;
return 0;
}
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
dprintk(DBGLVL_I2C, "%s(num = %d) addr = 0x%02x len = 0x%x\n",
__func__, num, msgs[i].addr, msgs[i].len);
if (msgs[i].flags & I2C_M_RD) {
- /* Unsupported - Yet*/
- printk(KERN_ERR "%s() Unsupported - Yet\n", __func__);
- continue;
+ retval = saa7164_api_i2c_read(bus,
+ msgs[i].addr,
+ 0 /* reglen */,
+ 0 /* reg */, msgs[i].len, msgs[i].buf);
} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
msgs[i].addr == msgs[i + 1].addr) {
/* write then read from same address */
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
sizeof(cap->card));
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
- cap->capabilities =
+ cap->device_caps =
V4L2_CAP_VBI_CAPTURE |
- V4L2_CAP_READWRITE |
- 0;
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_TUNER;
- cap->capabilities |= V4L2_CAP_TUNER;
- cap->version = 0;
+ cap->capabilities = cap->device_caps |
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_DEVICE_CAPS;
return 0;
}
/*
* Driver for the NXP SAA7164 PCIe bridge
*
- * Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ * Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
*
* 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
#define SAA7164_BOARD_HAUPPAUGE_HVR2250_3 8
#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4 9
#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5 10
+#define SAA7164_BOARD_HAUPPAUGE_HVR2255proto 11
+#define SAA7164_BOARD_HAUPPAUGE_HVR2255 12
+#define SAA7164_BOARD_HAUPPAUGE_HVR2205 13
#define SAA7164_MAX_UNITS 8
#define SAA7164_TS_NUMBER_OF_LINES 312
/* --- DVB Transport Specific --- */
struct saa7164_dvb dvb;
+ struct i2c_client *i2c_client_demod;
+ struct i2c_client *i2c_client_tuner;
/* --- Encoder/V4L related attributes --- */
/* Encoder */
jpeg_codec_sleep(zr, 1);
jpeg_codec_sleep(zr, 0);
- /* set individual interrupt enables (without GIRQ1)
- * but don't global enable until zoran_open() */
-
- //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR); // SW
- // It looks like using only JPEGRepIRQEn is not always reliable,
- // may be when JPEG codec crashes it won't generate IRQ? So,
- /*CP*/ // btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM WHY ? LP
- zr36057_init_vfe(zr);
+ /*
+ * set individual interrupt enables (without GIRQ1)
+ * but don't global enable until zoran_open()
+ */
+ zr36057_init_vfe(zr);
zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
struct vpfe_ccdc_config_params_raw *config_params =
&ccdc->ccdc_cfg.bayer.config_params;
- config_params = raw_params;
+ *config_params = *raw_params;
}
/*
if (!vpfe_ccdc_validate_param(ccdc, &raw_params)) {
vpfe_ccdc_update_raw_params(ccdc, &raw_params);
- return 0;
+ return 0;
}
return -EINVAL;
* For a given standard, this functions sets up the default
* pix format & crop values in the vpfe device and ccdc. It first
* starts with defaults based values from the standard table.
- * It then checks if sub device support g_mbus_fmt and then override the
+ * It then checks if sub device supports get_fmt and then override the
* values based on that.Sets crop values to match with scan resolution
* starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
* values in ccdc
} else {
ret = v4l2_device_call_until_err(&vpfe->v4l2_dev,
sdinfo->grp_id,
- video, g_mbus_fmt,
- &mbus_fmt);
+ pad, get_fmt,
+ NULL, &fmt);
if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
return ret;
v4l2_fill_pix_format(&format->fmt.pix, &mbus_fmt);
static int __vpfe_set_format(struct vpfe_device *vpfe,
struct v4l2_format *format, unsigned int *bpp)
{
- struct v4l2_mbus_framefmt mbus_fmt;
struct vpfe_subdev_info *sdinfo;
struct v4l2_subdev_format fmt;
int ret;
pix_to_mbus(vpfe, &format->fmt.pix, &fmt.format);
ret = v4l2_subdev_call(sdinfo->sd, pad, set_fmt, NULL, &fmt);
- if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
+ if (ret)
return ret;
- if (!ret) {
- v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
- mbus_to_pix(vpfe, &fmt.format, &format->fmt.pix, bpp);
- } else {
- ret = v4l2_device_call_until_err(&vpfe->v4l2_dev,
- sdinfo->grp_id,
- video, s_mbus_fmt,
- &mbus_fmt);
- if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
- return ret;
-
- v4l2_fill_pix_format(&format->fmt.pix, &mbus_fmt);
- mbus_to_pix(vpfe, &mbus_fmt, &format->fmt.pix, bpp);
- }
+ v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
+ mbus_to_pix(vpfe, &fmt.format, &format->fmt.pix, bpp);
format->type = vpfe->fmt.type;
int *subdev_input_index,
int app_input_index)
{
- struct vpfe_config *cfg = vpfe->cfg;
- struct vpfe_subdev_info *sdinfo;
int i, j = 0;
for (i = 0; i < ARRAY_SIZE(vpfe->cfg->asd); i++) {
- sdinfo = &cfg->sub_devs[i];
if (app_input_index < (j + 1)) {
*subdev_index = i;
*subdev_input_index = app_input_index - j;
static int bcap_init_sensor_formats(struct bcap_device *bcap_dev)
{
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
struct bcap_format *sf;
unsigned int num_formats = 0;
int i, j;
- while (!v4l2_subdev_call(bcap_dev->sd, video,
- enum_mbus_fmt, num_formats, &code))
+ while (!v4l2_subdev_call(bcap_dev->sd, pad,
+ enum_mbus_code, NULL, &code)) {
num_formats++;
+ code.index++;
+ }
if (!num_formats)
return -ENXIO;
return -ENOMEM;
for (i = 0; i < num_formats; i++) {
- v4l2_subdev_call(bcap_dev->sd, video,
- enum_mbus_fmt, i, &code);
+ code.index = i;
+ v4l2_subdev_call(bcap_dev->sd, pad,
+ enum_mbus_code, NULL, &code);
for (j = 0; j < BCAP_MAX_FMTS; j++)
- if (code == bcap_formats[j].mbus_code)
+ if (code.code == bcap_formats[j].mbus_code)
break;
if (j == BCAP_MAX_FMTS) {
/* we don't allow this sensor working with our bridge */
{
struct bcap_format *sf = bcap->sensor_formats;
struct bcap_format *fmt = NULL;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
int ret, i;
for (i = 0; i < bcap->num_sensor_formats; i++) {
if (i == bcap->num_sensor_formats)
fmt = &sf[0];
- v4l2_fill_mbus_format(&mbus_fmt, pixfmt, fmt->mbus_code);
- ret = v4l2_subdev_call(bcap->sd, video,
- try_mbus_fmt, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, pixfmt, fmt->mbus_code);
+ ret = v4l2_subdev_call(bcap->sd, pad, set_fmt, &pad_cfg,
+ &format);
if (ret < 0)
return ret;
- v4l2_fill_pix_format(pixfmt, &mbus_fmt);
+ v4l2_fill_pix_format(pixfmt, &format.format);
if (bcap_fmt) {
for (i = 0; i < bcap->num_sensor_formats; i++) {
fmt = &sf[i];
- if (mbus_fmt.code == fmt->mbus_code)
+ if (format.format.code == fmt->mbus_code)
break;
}
*bcap_fmt = *fmt;
struct v4l2_format *fmt)
{
struct bcap_device *bcap_dev = video_drvdata(file);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
struct bcap_format bcap_fmt;
struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
int ret;
if (ret < 0)
return ret;
- v4l2_fill_mbus_format(&mbus_fmt, pixfmt, bcap_fmt.mbus_code);
- ret = v4l2_subdev_call(bcap_dev->sd, video, s_mbus_fmt, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, pixfmt, bcap_fmt.mbus_code);
+ ret = v4l2_subdev_call(bcap_dev->sd, pad, set_fmt, NULL, &format);
if (ret < 0)
return ret;
bcap_dev->fmt = *pixfmt;
* For a given standard, this functions sets up the default
* pix format & crop values in the vpfe device and ccdc. It first
* starts with defaults based values from the standard table.
- * It then checks if sub device support g_mbus_fmt and then override the
+ * It then checks if sub device supports get_fmt and then override the
* values based on that.Sets crop values to match with scan resolution
* starting at 0,0. It calls vpfe_config_ccdc_image_format() set the
* values in ccdc
v4l2_std_id std_id)
{
struct vpfe_subdev_info *sdinfo = vpfe_dev->current_subdev;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
struct v4l2_pix_format *pix = &vpfe_dev->fmt.fmt.pix;
int i, ret = 0;
pix->field = V4L2_FIELD_INTERLACED;
/* assume V4L2_PIX_FMT_UYVY as default */
pix->pixelformat = V4L2_PIX_FMT_UYVY;
- v4l2_fill_mbus_format(&mbus_fmt, pix,
+ v4l2_fill_mbus_format(mbus_fmt, pix,
MEDIA_BUS_FMT_YUYV10_2X10);
} else {
pix->field = V4L2_FIELD_NONE;
/* assume V4L2_PIX_FMT_SBGGR8 */
pix->pixelformat = V4L2_PIX_FMT_SBGGR8;
- v4l2_fill_mbus_format(&mbus_fmt, pix,
+ v4l2_fill_mbus_format(mbus_fmt, pix,
MEDIA_BUS_FMT_SBGGR8_1X8);
}
- /* if sub device supports g_mbus_fmt, override the defaults */
+ /* if sub device supports get_fmt, override the defaults */
ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
- sdinfo->grp_id, video, g_mbus_fmt, &mbus_fmt);
+ sdinfo->grp_id, pad, get_fmt, NULL, &fmt);
if (ret && ret != -ENOIOCTLCMD) {
v4l2_err(&vpfe_dev->v4l2_dev,
- "error in getting g_mbus_fmt from sub device\n");
+ "error in getting get_fmt from sub device\n");
return ret;
}
- v4l2_fill_pix_format(pix, &mbus_fmt);
+ v4l2_fill_pix_format(pix, mbus_fmt);
pix->bytesperline = pix->width * 2;
pix->sizeimage = pix->bytesperline * pix->height;
return 0;
- v4l2_m2m_release(pcdev->m2m_dev);
err_m2m:
video_unregister_device(&pcdev->vfd);
err_ctx:
adap = kzalloc(sizeof(*adap), GFP_KERNEL);
if (adap == NULL)
return -ENOMEM;
- cam->mcam.i2c_adapter = adap;
- cafe_smbus_enable_irq(cam);
adap->owner = THIS_MODULE;
adap->algo = &cafe_smbus_algo;
strcpy(adap->name, "cafe_ccic");
adap->dev.parent = &cam->pdev->dev;
i2c_set_adapdata(adap, cam);
ret = i2c_add_adapter(adap);
- if (ret)
+ if (ret) {
printk(KERN_ERR "Unable to register cafe i2c adapter\n");
- return ret;
+ kfree(adap);
+ return ret;
+ }
+
+ cam->mcam.i2c_adapter = adap;
+ cafe_smbus_enable_irq(cam);
+ return 0;
}
static void cafe_smbus_shutdown(struct cafe_camera *cam)
mcam->plat_power_up = cafe_ctlr_power_up;
mcam->plat_power_down = cafe_ctlr_power_down;
mcam->dev = &pdev->dev;
+ snprintf(mcam->bus_info, sizeof(mcam->bus_info), "PCI:%s", pci_name(pdev));
/*
* Set the clock speed for the XO 1; I don't believe this
* driver has ever run anywhere else.
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
#include <media/ov7670.h>
#include <media/videobuf2-vmalloc.h>
#include <media/videobuf2-dma-contig.h>
.bpp = 2,
.planar = false,
},
- {
- .desc = "YUV 4:2:2 PLANAR",
- .pixelformat = V4L2_PIX_FMT_YUV422P,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
- .bpp = 2,
- .planar = true,
- },
{
.desc = "YUV 4:2:0 PLANAR",
.pixelformat = V4L2_PIX_FMT_YUV420,
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
- .bpp = 2,
+ .bpp = 1,
.planar = true,
},
{
.desc = "YVU 4:2:0 PLANAR",
.pixelformat = V4L2_PIX_FMT_YVU420,
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
- .bpp = 2,
+ .bpp = 1,
.planar = true,
},
{
.field = V4L2_FIELD_NONE,
.bytesperline = VGA_WIDTH*2,
.sizeimage = VGA_WIDTH*VGA_HEIGHT*2,
+ .colorspace = V4L2_COLORSPACE_SRGB,
};
static const u32 mcam_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
u32 segment_len;
};
-struct yuv_pointer_t {
- dma_addr_t y;
- dma_addr_t u;
- dma_addr_t v;
-};
-
/*
* Our buffer type for working with videobuf2. Note that the vb2
* developers have decreed that struct vb2_buffer must be at the
struct mcam_dma_desc *dma_desc; /* Descriptor virtual address */
dma_addr_t dma_desc_pa; /* Descriptor physical address */
int dma_desc_nent; /* Number of mapped descriptors */
- struct yuv_pointer_t yuv_p;
};
static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
{
vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
vbuf->v4l2_buf.sequence = cam->buf_seq[frame];
+ vbuf->v4l2_buf.field = V4L2_FIELD_NONE;
+ v4l2_get_timestamp(&vbuf->v4l2_buf.timestamp);
vb2_set_plane_payload(vbuf, 0, cam->pix_format.sizeimage);
vb2_buffer_done(vbuf, VB2_BUF_STATE_DONE);
}
mcam->mipi_enabled = false;
}
+static bool mcam_fmt_is_planar(__u32 pfmt)
+{
+ struct mcam_format_struct *f;
+
+ f = mcam_find_format(pfmt);
+ return f->planar;
+}
+
+static void mcam_write_yuv_bases(struct mcam_camera *cam,
+ unsigned frame, dma_addr_t base)
+{
+ struct v4l2_pix_format *fmt = &cam->pix_format;
+ u32 pixel_count = fmt->width * fmt->height;
+ dma_addr_t y, u = 0, v = 0;
+
+ y = base;
+
+ switch (fmt->pixelformat) {
+ case V4L2_PIX_FMT_YUV420:
+ u = y + pixel_count;
+ v = u + pixel_count / 4;
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v = y + pixel_count;
+ u = v + pixel_count / 4;
+ break;
+ default:
+ break;
+ }
+
+ mcam_reg_write(cam, REG_Y0BAR + frame * 4, y);
+ if (mcam_fmt_is_planar(fmt->pixelformat)) {
+ mcam_reg_write(cam, REG_U0BAR + frame * 4, u);
+ mcam_reg_write(cam, REG_V0BAR + frame * 4, v);
+ }
+}
+
/* ------------------------------------------------------------------- */
#ifdef MCAM_MODE_VMALLOC
static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
{
/*
- * Store the first two Y buffers (we aren't supporting
- * planar formats for now, so no UV bufs). Then either
+ * Store the first two YUV buffers. Then either
* set the third if it exists, or tell the controller
* to just use two.
*/
- mcam_reg_write(cam, REG_Y0BAR, cam->dma_handles[0]);
- mcam_reg_write(cam, REG_Y1BAR, cam->dma_handles[1]);
+ mcam_write_yuv_bases(cam, 0, cam->dma_handles[0]);
+ mcam_write_yuv_bases(cam, 1, cam->dma_handles[1]);
if (cam->nbufs > 2) {
- mcam_reg_write(cam, REG_Y2BAR, cam->dma_handles[2]);
+ mcam_write_yuv_bases(cam, 2, cam->dma_handles[2]);
mcam_reg_clear_bit(cam, REG_CTRL1, C1_TWOBUFS);
} else
mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
* DMA-contiguous code.
*/
-static bool mcam_fmt_is_planar(__u32 pfmt)
-{
- struct mcam_format_struct *f;
-
- f = mcam_find_format(pfmt);
- return f->planar;
-}
-
/*
* Set up a contiguous buffer for the given frame. Here also is where
* the underrun strategy is set: if there is no buffer available, reuse
static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
{
struct mcam_vb_buffer *buf;
- struct v4l2_pix_format *fmt = &cam->pix_format;
dma_addr_t dma_handle;
- u32 pixel_count = fmt->width * fmt->height;
struct vb2_buffer *vb;
/*
vb = &buf->vb_buf;
dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
- buf->yuv_p.y = dma_handle;
-
- switch (cam->pix_format.pixelformat) {
- case V4L2_PIX_FMT_YUV422P:
- buf->yuv_p.u = buf->yuv_p.y + pixel_count;
- buf->yuv_p.v = buf->yuv_p.u + pixel_count / 2;
- break;
- case V4L2_PIX_FMT_YUV420:
- buf->yuv_p.u = buf->yuv_p.y + pixel_count;
- buf->yuv_p.v = buf->yuv_p.u + pixel_count / 4;
- break;
- case V4L2_PIX_FMT_YVU420:
- buf->yuv_p.v = buf->yuv_p.y + pixel_count;
- buf->yuv_p.u = buf->yuv_p.v + pixel_count / 4;
- break;
- default:
- break;
- }
-
- mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
- if (mcam_fmt_is_planar(fmt->pixelformat)) {
- mcam_reg_write(cam, frame == 0 ?
- REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
- mcam_reg_write(cam, frame == 0 ?
- REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
- }
+ mcam_write_yuv_bases(cam, frame, dma_handle);
}
/*
if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) {
cam->frame_state.delivered++;
+ cam->vb_bufs[frame] = NULL;
mcam_buffer_done(cam, frame, &buf->vb_buf);
}
mcam_set_contig_buffer(cam, frame);
widthy = fmt->width * 2;
widthuv = 0;
break;
- case V4L2_PIX_FMT_JPEG:
- imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
- widthy = fmt->bytesperline;
- widthuv = 0;
- break;
- case V4L2_PIX_FMT_YUV422P:
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
widthy = fmt->width;
default:
widthy = fmt->bytesperline;
widthuv = 0;
+ break;
}
mcam_reg_write_mask(cam, REG_IMGPITCH, widthuv << 16 | widthy,
* Tell the controller about the image format we are using.
*/
switch (fmt->pixelformat) {
- case V4L2_PIX_FMT_YUV422P:
- mcam_reg_write_mask(cam, REG_CTRL0,
- C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
- break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
mcam_reg_write_mask(cam, REG_CTRL0,
mcam_reg_write_mask(cam, REG_CTRL0,
C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_SWAP24, C0_DF_MASK);
break;
- case V4L2_PIX_FMT_JPEG:
- mcam_reg_write_mask(cam, REG_CTRL0,
- C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
- break;
case V4L2_PIX_FMT_RGB444:
mcam_reg_write_mask(cam, REG_CTRL0,
C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
mcam_reg_write_mask(cam, REG_CTRL0,
C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
break;
+ case V4L2_PIX_FMT_SBGGR8:
+ mcam_reg_write_mask(cam, REG_CTRL0,
+ C0_DF_RGB | C0_RGB5_GRBG, C0_DF_MASK);
+ break;
default:
cam_err(cam, "camera: unknown format: %#x\n", fmt->pixelformat);
break;
{
int ret;
- mutex_lock(&cam->s_mutex);
if (cam->state != S_NOTREADY)
cam_warn(cam, "Cam init with device in funky state %d",
cam->state);
/* Get/set parameters? */
cam->state = S_IDLE;
mcam_ctlr_power_down(cam);
- mutex_unlock(&cam->s_mutex);
return ret;
}
static int mcam_cam_configure(struct mcam_camera *cam)
{
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int ret;
- v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code);
+ v4l2_fill_mbus_format(&format.format, &cam->pix_format, cam->mbus_code);
ret = sensor_call(cam, core, init, 0);
if (ret == 0)
- ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt);
+ ret = sensor_call(cam, pad, set_fmt, NULL, &format);
/*
* OV7670 does weird things if flip is set *before* format...
*/
struct mcam_camera *cam = vb2_get_drv_priv(vq);
int minbufs = (cam->buffer_mode == B_DMA_contig) ? 3 : 2;
- sizes[0] = cam->pix_format.sizeimage;
+ if (fmt && fmt->fmt.pix.sizeimage < cam->pix_format.sizeimage)
+ return -EINVAL;
+ sizes[0] = fmt ? fmt->fmt.pix.sizeimage : cam->pix_format.sizeimage;
*num_planes = 1; /* Someday we have to support planar formats... */
if (*nbufs < minbufs)
*nbufs = minbufs;
mcam_read_setup(cam);
}
+static void mcam_vb_requeue_bufs(struct vb2_queue *vq,
+ enum vb2_buffer_state state)
+{
+ struct mcam_camera *cam = vb2_get_drv_priv(vq);
+ struct mcam_vb_buffer *buf, *node;
+ unsigned long flags;
+ unsigned i;
+
+ spin_lock_irqsave(&cam->dev_lock, flags);
+ list_for_each_entry_safe(buf, node, &cam->buffers, queue) {
+ vb2_buffer_done(&buf->vb_buf, state);
+ list_del(&buf->queue);
+ }
+ for (i = 0; i < MAX_DMA_BUFS; i++) {
+ buf = cam->vb_bufs[i];
+
+ if (buf) {
+ vb2_buffer_done(&buf->vb_buf, state);
+ cam->vb_bufs[i] = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&cam->dev_lock, flags);
+}
+
/*
* These need to be called with the mutex held from vb2
*/
{
struct mcam_camera *cam = vb2_get_drv_priv(vq);
unsigned int frame;
+ int ret;
if (cam->state != S_IDLE) {
- INIT_LIST_HEAD(&cam->buffers);
+ mcam_vb_requeue_bufs(vq, VB2_BUF_STATE_QUEUED);
return -EINVAL;
}
+ cam->frame_state.frames = 0;
+ cam->frame_state.singles = 0;
+ cam->frame_state.delivered = 0;
cam->sequence = 0;
/*
* Videobuf2 sneakily hoards all the buffers and won't
for (frame = 0; frame < cam->nbufs; frame++)
clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
- return mcam_read_setup(cam);
+ ret = mcam_read_setup(cam);
+ if (ret)
+ mcam_vb_requeue_bufs(vq, VB2_BUF_STATE_QUEUED);
+ return ret;
}
static void mcam_vb_stop_streaming(struct vb2_queue *vq)
{
struct mcam_camera *cam = vb2_get_drv_priv(vq);
- unsigned long flags;
+ cam_dbg(cam, "stop_streaming: %d frames, %d singles, %d delivered\n",
+ cam->frame_state.frames, cam->frame_state.singles,
+ cam->frame_state.delivered);
if (cam->state == S_BUFWAIT) {
/* They never gave us buffers */
cam->state = S_IDLE;
* VB2 reclaims the buffers, so we need to forget
* about them.
*/
- spin_lock_irqsave(&cam->dev_lock, flags);
- INIT_LIST_HEAD(&cam->buffers);
- spin_unlock_irqrestore(&cam->dev_lock, flags);
+ mcam_vb_requeue_bufs(vq, VB2_BUF_STATE_ERROR);
}
vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vq->drv_priv = cam;
vq->lock = &cam->s_mutex;
+ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
+ vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
INIT_LIST_HEAD(&cam->buffers);
switch (cam->buffer_mode) {
case B_DMA_contig:
#ifdef MCAM_MODE_DMA_CONTIG
vq->ops = &mcam_vb2_ops;
vq->mem_ops = &vb2_dma_contig_memops;
- vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
- vq->io_modes = VB2_MMAP | VB2_USERPTR;
cam->dma_setup = mcam_ctlr_dma_contig;
cam->frame_complete = mcam_dma_contig_done;
cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
#ifdef MCAM_MODE_DMA_SG
vq->ops = &mcam_vb2_sg_ops;
vq->mem_ops = &vb2_dma_sg_memops;
- vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
- vq->io_modes = VB2_MMAP | VB2_USERPTR;
cam->dma_setup = mcam_ctlr_dma_sg;
cam->frame_complete = mcam_dma_sg_done;
cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);
(unsigned long) cam);
vq->ops = &mcam_vb2_ops;
vq->mem_ops = &vb2_vmalloc_memops;
- vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
- vq->io_modes = VB2_MMAP;
cam->dma_setup = mcam_ctlr_dma_vmalloc;
cam->frame_complete = mcam_vmalloc_done;
#endif
static void mcam_cleanup_vb2(struct mcam_camera *cam)
{
- vb2_queue_release(&cam->vb_queue);
#ifdef MCAM_MODE_DMA_CONTIG
if (cam->buffer_mode == B_DMA_contig)
vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
* The long list of V4L2 ioctl() operations.
*/
-static int mcam_vidioc_streamon(struct file *filp, void *priv,
- enum v4l2_buf_type type)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_streamon(&cam->vb_queue, type);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-
-static int mcam_vidioc_streamoff(struct file *filp, void *priv,
- enum v4l2_buf_type type)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_streamoff(&cam->vb_queue, type);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-
-static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
- struct v4l2_requestbuffers *req)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_reqbufs(&cam->vb_queue, req);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-
-static int mcam_vidioc_querybuf(struct file *filp, void *priv,
- struct v4l2_buffer *buf)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_querybuf(&cam->vb_queue, buf);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-static int mcam_vidioc_qbuf(struct file *filp, void *priv,
- struct v4l2_buffer *buf)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_qbuf(&cam->vb_queue, buf);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-static int mcam_vidioc_dqbuf(struct file *filp, void *priv,
- struct v4l2_buffer *buf)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
static int mcam_vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
+ struct mcam_camera *cam = video_drvdata(file);
+
strcpy(cap->driver, "marvell_ccic");
strcpy(cap->card, "marvell_ccic");
+ strlcpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *fmt)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
struct mcam_format_struct *f;
struct v4l2_pix_format *pix = &fmt->fmt.pix;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
int ret;
f = mcam_find_format(pix->pixelformat);
pix->pixelformat = f->pixelformat;
- v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
- mutex_lock(&cam->s_mutex);
- ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
- mutex_unlock(&cam->s_mutex);
- v4l2_fill_pix_format(pix, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, pix, f->mbus_code);
+ ret = sensor_call(cam, pad, set_fmt, &pad_cfg, &format);
+ v4l2_fill_pix_format(pix, &format.format);
+ pix->bytesperline = pix->width * f->bpp;
switch (f->pixelformat) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- pix->bytesperline = pix->width * 3 / 2;
+ pix->sizeimage = pix->height * pix->bytesperline * 3 / 2;
break;
default:
- pix->bytesperline = pix->width * f->bpp;
+ pix->sizeimage = pix->height * pix->bytesperline;
break;
}
- pix->sizeimage = pix->height * pix->bytesperline;
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
return ret;
}
static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *fmt)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
struct mcam_format_struct *f;
int ret;
* Can't do anything if the device is not idle
* Also can't if there are streaming buffers in place.
*/
- if (cam->state != S_IDLE || cam->vb_queue.num_buffers > 0)
+ if (cam->state != S_IDLE || vb2_is_busy(&cam->vb_queue))
return -EBUSY;
f = mcam_find_format(fmt->fmt.pix.pixelformat);
* Now we start to change things for real, so let's do it
* under lock.
*/
- mutex_lock(&cam->s_mutex);
cam->pix_format = fmt->fmt.pix;
cam->mbus_code = f->mbus_code;
}
mcam_set_config_needed(cam, 1);
out:
- mutex_unlock(&cam->s_mutex);
return ret;
}
static int mcam_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_format *f)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
f->fmt.pix = cam->pix_format;
return 0;
return -EINVAL;
input->type = V4L2_INPUT_TYPE_CAMERA;
- input->std = V4L2_STD_ALL; /* Not sure what should go here */
strcpy(input->name, "Camera");
return 0;
}
return 0;
}
-/* from vivi.c */
-static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a)
-{
- return 0;
-}
-
-static int mcam_vidioc_g_std(struct file *filp, void *priv, v4l2_std_id *a)
-{
- *a = V4L2_STD_NTSC_M;
- return 0;
-}
-
/*
* G/S_PARM. Most of this is done by the sensor, but we are
* the level which controls the number of read buffers.
static int mcam_vidioc_g_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parms)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
int ret;
- mutex_lock(&cam->s_mutex);
ret = sensor_call(cam, video, g_parm, parms);
- mutex_unlock(&cam->s_mutex);
parms->parm.capture.readbuffers = n_dma_bufs;
return ret;
}
static int mcam_vidioc_s_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parms)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
int ret;
- mutex_lock(&cam->s_mutex);
ret = sensor_call(cam, video, s_parm, parms);
- mutex_unlock(&cam->s_mutex);
parms->parm.capture.readbuffers = n_dma_bufs;
return ret;
}
static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv,
struct v4l2_frmsizeenum *sizes)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
struct mcam_format_struct *f;
struct v4l2_subdev_frame_size_enum fse = {
.index = sizes->index,
if (f->pixelformat != sizes->pixel_format)
return -EINVAL;
fse.code = f->mbus_code;
- mutex_lock(&cam->s_mutex);
ret = sensor_call(cam, pad, enum_frame_size, NULL, &fse);
- mutex_unlock(&cam->s_mutex);
if (ret)
return ret;
if (fse.min_width == fse.max_width &&
static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv,
struct v4l2_frmivalenum *interval)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(filp);
struct mcam_format_struct *f;
struct v4l2_subdev_frame_interval_enum fie = {
.index = interval->index,
if (f->pixelformat != interval->pixel_format)
return -EINVAL;
fie.code = f->mbus_code;
- mutex_lock(&cam->s_mutex);
ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie);
- mutex_unlock(&cam->s_mutex);
if (ret)
return ret;
interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
static int mcam_vidioc_g_register(struct file *file, void *priv,
struct v4l2_dbg_register *reg)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(file);
if (reg->reg > cam->regs_size - 4)
return -EINVAL;
static int mcam_vidioc_s_register(struct file *file, void *priv,
const struct v4l2_dbg_register *reg)
{
- struct mcam_camera *cam = priv;
+ struct mcam_camera *cam = video_drvdata(file);
if (reg->reg > cam->regs_size - 4)
return -EINVAL;
.vidioc_enum_input = mcam_vidioc_enum_input,
.vidioc_g_input = mcam_vidioc_g_input,
.vidioc_s_input = mcam_vidioc_s_input,
- .vidioc_s_std = mcam_vidioc_s_std,
- .vidioc_g_std = mcam_vidioc_g_std,
- .vidioc_reqbufs = mcam_vidioc_reqbufs,
- .vidioc_querybuf = mcam_vidioc_querybuf,
- .vidioc_qbuf = mcam_vidioc_qbuf,
- .vidioc_dqbuf = mcam_vidioc_dqbuf,
- .vidioc_streamon = mcam_vidioc_streamon,
- .vidioc_streamoff = mcam_vidioc_streamoff,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_expbuf = vb2_ioctl_expbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_g_parm = mcam_vidioc_g_parm,
.vidioc_s_parm = mcam_vidioc_s_parm,
.vidioc_enum_framesizes = mcam_vidioc_enum_framesizes,
.vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.vidioc_g_register = mcam_vidioc_g_register,
.vidioc_s_register = mcam_vidioc_s_register,
static int mcam_v4l_open(struct file *filp)
{
struct mcam_camera *cam = video_drvdata(filp);
- int ret = 0;
-
- filp->private_data = cam;
+ int ret;
- cam->frame_state.frames = 0;
- cam->frame_state.singles = 0;
- cam->frame_state.delivered = 0;
mutex_lock(&cam->s_mutex);
- if (cam->users == 0) {
- ret = mcam_setup_vb2(cam);
- if (ret)
- goto out;
+ ret = v4l2_fh_open(filp);
+ if (ret)
+ goto out;
+ if (v4l2_fh_is_singular_file(filp)) {
ret = mcam_ctlr_power_up(cam);
if (ret)
goto out;
__mcam_cam_reset(cam);
mcam_set_config_needed(cam, 1);
}
- (cam->users)++;
out:
mutex_unlock(&cam->s_mutex);
+ if (ret)
+ v4l2_fh_release(filp);
return ret;
}
static int mcam_v4l_release(struct file *filp)
{
- struct mcam_camera *cam = filp->private_data;
+ struct mcam_camera *cam = video_drvdata(filp);
+ bool last_open;
- cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
- cam->frame_state.frames, cam->frame_state.singles,
- cam->frame_state.delivered);
mutex_lock(&cam->s_mutex);
- (cam->users)--;
- if (cam->users == 0) {
- mcam_ctlr_stop_dma(cam);
- mcam_cleanup_vb2(cam);
+ last_open = v4l2_fh_is_singular_file(filp);
+ _vb2_fop_release(filp, NULL);
+ if (last_open) {
mcam_disable_mipi(cam);
mcam_ctlr_power_down(cam);
if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
return 0;
}
-static ssize_t mcam_v4l_read(struct file *filp,
- char __user *buffer, size_t len, loff_t *pos)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_read(&cam->vb_queue, buffer, len, pos,
- filp->f_flags & O_NONBLOCK);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-
-
-static unsigned int mcam_v4l_poll(struct file *filp,
- struct poll_table_struct *pt)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_poll(&cam->vb_queue, filp, pt);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-
-static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct mcam_camera *cam = filp->private_data;
- int ret;
-
- mutex_lock(&cam->s_mutex);
- ret = vb2_mmap(&cam->vb_queue, vma);
- mutex_unlock(&cam->s_mutex);
- return ret;
-}
-
-
-
static const struct v4l2_file_operations mcam_v4l_fops = {
.owner = THIS_MODULE,
.open = mcam_v4l_open,
.release = mcam_v4l_release,
- .read = mcam_v4l_read,
- .poll = mcam_v4l_poll,
- .mmap = mcam_v4l_mmap,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
.unlocked_ioctl = video_ioctl2,
};
*/
static struct video_device mcam_v4l_template = {
.name = "mcam",
- .tvnorms = V4L2_STD_NTSC_M,
-
.fops = &mcam_v4l_fops,
.ioctl_ops = &mcam_v4l_ioctl_ops,
.release = video_device_release_empty,
set_bit(frame, &cam->flags);
clear_bit(CF_DMA_ACTIVE, &cam->flags);
cam->next_buf = frame;
- cam->buf_seq[frame] = ++(cam->sequence);
+ cam->buf_seq[frame] = cam->sequence++;
cam->frame_state.frames++;
/*
* "This should never happen"
mcam_set_config_needed(cam, 1);
cam->pix_format = mcam_def_pix_format;
cam->mbus_code = mcam_def_mbus_code;
- INIT_LIST_HEAD(&cam->buffers);
mcam_ctlr_init(cam);
+ /*
+ * Get the v4l2 setup done.
+ */
+ ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
+ if (ret)
+ goto out_unregister;
+ cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
+
/*
* Try to find the sensor.
*/
ret = mcam_cam_init(cam);
if (ret)
goto out_unregister;
- /*
- * Get the v4l2 setup done.
- */
- ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
+
+ ret = mcam_setup_vb2(cam);
if (ret)
goto out_unregister;
- cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
mutex_lock(&cam->s_mutex);
cam->vdev = mcam_v4l_template;
cam->vdev.v4l2_dev = &cam->v4l2_dev;
+ cam->vdev.lock = &cam->s_mutex;
+ cam->vdev.queue = &cam->vb_queue;
video_set_drvdata(&cam->vdev, cam);
ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
- if (ret)
- goto out;
+ if (ret) {
+ mutex_unlock(&cam->s_mutex);
+ goto out_unregister;
+ }
/*
* If so requested, try to get our DMA buffers now.
" will try again later.");
}
-out:
- v4l2_ctrl_handler_free(&cam->ctrl_handler);
mutex_unlock(&cam->s_mutex);
- return ret;
+ return 0;
+
out_unregister:
+ v4l2_ctrl_handler_free(&cam->ctrl_handler);
v4l2_device_unregister(&cam->v4l2_dev);
return ret;
}
* take it down again will wedge the machine, which is frowned
* upon.
*/
- if (cam->users > 0) {
+ if (!list_empty(&cam->vdev.fh_list)) {
cam_warn(cam, "Removing a device with users!\n");
mcam_ctlr_power_down(cam);
}
- vb2_queue_release(&cam->vb_queue);
+ mcam_cleanup_vb2(cam);
if (cam->buffer_mode == B_vmalloc)
mcam_free_dma_bufs(cam);
video_unregister_device(&cam->vdev);
void mccic_suspend(struct mcam_camera *cam)
{
mutex_lock(&cam->s_mutex);
- if (cam->users > 0) {
+ if (!list_empty(&cam->vdev.fh_list)) {
enum mcam_state cstate = cam->state;
mcam_ctlr_stop_dma(cam);
int ret = 0;
mutex_lock(&cam->s_mutex);
- if (cam->users > 0) {
+ if (!list_empty(&cam->vdev.fh_list)) {
ret = mcam_ctlr_power_up(cam);
if (ret) {
mutex_unlock(&cam->s_mutex);
struct v4l2_ctrl_handler ctrl_handler;
enum mcam_state state;
unsigned long flags; /* Buffer status, mainly (dev_lock) */
- int users; /* How many open FDs */
struct mcam_frame_state frame_state; /* Frame state counter */
/*
unsigned int nbufs; /* How many are alloc'd */
int next_buf; /* Next to consume (dev_lock) */
+ char bus_info[32]; /* querycap bus_info */
+
/* DMA buffers - vmalloc mode */
#ifdef MCAM_MODE_VMALLOC
unsigned int dma_buf_size; /* allocated size */
mcam->lane = pdata->lane;
mcam->chip_id = MCAM_ARMADA610;
mcam->buffer_mode = B_DMA_sg;
+ strlcpy(mcam->bus_info, "platform:mmp-camera", sizeof(mcam->bus_info));
spin_lock_init(&mcam->dev_lock);
/*
* Get our I/O memory.
struct cam_sensor *sensor = &camif->sensor;
int err = 0;
- if (!on == camif->sensor.power_count)
+ if (camif->sensor.power_count == !on)
err = v4l2_subdev_call(sensor->sd, core, s_power, on);
if (!err)
sensor->power_count += on ? 1 : -1;
struct cam_sensor *sensor = &camif->sensor;
int err = 0;
- if (!on == camif->sensor.stream_count)
+ if (camif->sensor.stream_count == !on)
err = v4l2_subdev_call(sensor->sd, video, s_stream, on);
if (!err)
sensor->stream_count += on ? 1 : -1;
struct camif_vp *vp = vb2_get_drv_priv(vq);
struct camif_dev *camif = vp->camif;
struct camif_frame *frame = &vp->out_frame;
- const struct camif_fmt *fmt = vp->out_fmt;
+ const struct camif_fmt *fmt;
unsigned int size;
if (pfmt) {
pix = &pfmt->fmt.pix;
fmt = s3c_camif_find_format(vp, &pix->pixelformat, -1);
+ if (fmt == NULL)
+ return -EINVAL;
size = (pix->width * pix->height * fmt->depth) / 8;
} else {
+ fmt = vp->out_fmt;
+ if (fmt == NULL)
+ return -EINVAL;
size = (frame->f_width * frame->f_height * fmt->depth) / 8;
}
- if (fmt == NULL)
- return -EINVAL;
*num_planes = 1;
if (pix)
struct platform_device *pdev = to_platform_device(dev);
struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
- if (!m_dev->alloc_ctx)
- return 0;
atomic_set(&m_dev->pm.power, 1);
return 0;
}
ret = s5p_mfc_alloc_priv_buf(dev->mem_dev_r, &ctx->bank2);
if (ret) {
mfc_err("Failed to allocate Bank2 temporary buffer\n");
- s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1);
+ s5p_mfc_release_priv_buf(ctx->dev->mem_dev_l, &ctx->bank1);
return ret;
}
BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
return 0;
}
-static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int hdmi_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
const struct hdmi_timings *t = hdev->cur_conf;
dev_dbg(hdev->dev, "%s\n", __func__);
if (!hdev->cur_conf)
return -EINVAL;
+ if (format->pad)
+ return -EINVAL;
+
memset(fmt, 0, sizeof(*fmt));
fmt->width = t->hact.end - t->hact.beg;
fmt->height = t->vact[0].end - t->vact[0].beg;
static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
.s_dv_timings = hdmi_s_dv_timings,
.g_dv_timings = hdmi_g_dv_timings,
- .g_mbus_fmt = hdmi_g_mbus_fmt,
.s_stream = hdmi_s_stream,
};
static const struct v4l2_subdev_pad_ops hdmi_sd_pad_ops = {
.enum_dv_timings = hdmi_enum_dv_timings,
.dv_timings_cap = hdmi_dv_timings_cap,
+ .get_fmt = hdmi_get_fmt,
};
static const struct v4l2_subdev_ops hdmi_sd_ops = {
.core = &hdmi_sd_core_ops,
.video = &hdmi_sd_video_ops,
+ .pad = &hdmi_sd_pad_ops,
};
static int hdmi_runtime_suspend(struct device *dev)
struct v4l2_mbus_framefmt *mbus_fmt)
{
struct v4l2_subdev *sd;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int ret;
mutex_lock(&mdev->mutex);
sd = to_outsd(mdev);
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, mbus_fmt);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
+ *mbus_fmt = fmt.format;
WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
mutex_unlock(&mdev->mutex);
}
mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer);
if (mdev->n_streamer == 1) {
struct v4l2_subdev *sd = to_outsd(mdev);
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
struct mxr_resources *res = &mdev->res;
int ret;
clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
mxr_reg_s_output(mdev, to_output(mdev)->cookie);
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
ret = v4l2_subdev_call(sd, video, s_stream, 1);
WARN(ret, "starting stream failed for output %s\n", sd->name);
- mxr_reg_set_mbus_fmt(mdev, &mbus_fmt);
+ mxr_reg_set_mbus_fmt(mdev, mbus_fmt);
mxr_reg_streamon(mdev);
ret = mxr_reg_wait4vsync(mdev);
WARN(ret, "failed to get vsync (%d) from output\n", ret);
return 0;
}
-static int sdo_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int sdo_get_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct sdo_device *sdev = sd_to_sdev(sd);
if (!sdev->fmt)
return -ENXIO;
+ if (format->pad)
+ return -EINVAL;
/* all modes are 720 pixels wide */
fmt->width = 720;
fmt->height = sdev->fmt->height;
.s_std_output = sdo_s_std_output,
.g_std_output = sdo_g_std_output,
.g_tvnorms_output = sdo_g_tvnorms_output,
- .g_mbus_fmt = sdo_g_mbus_fmt,
.s_stream = sdo_s_stream,
};
+static const struct v4l2_subdev_pad_ops sdo_sd_pad_ops = {
+ .get_fmt = sdo_get_fmt,
+};
+
static const struct v4l2_subdev_ops sdo_sd_ops = {
.core = &sdo_sd_core_ops,
.video = &sdo_sd_video_ops,
+ .pad = &sdo_sd_pad_ops,
};
static int sdo_runtime_suspend(struct device *dev)
unsigned int img_height_max;
int pix_idx;
struct sh_vou_geometry geo;
- struct v4l2_mbus_framefmt mbfmt = {
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
/* Revisit: is this the correct code? */
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
- .field = V4L2_FIELD_INTERLACED,
- .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ .format.code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .format.field = V4L2_FIELD_INTERLACED,
+ .format.colorspace = V4L2_COLORSPACE_SMPTE170M,
};
+ struct v4l2_mbus_framefmt *mbfmt = &format.format;
int ret;
dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__,
vou_adjust_output(&geo, vou_dev->std);
- mbfmt.width = geo.output.width;
- mbfmt.height = geo.output.height;
- ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
- s_mbus_fmt, &mbfmt);
+ mbfmt->width = geo.output.width;
+ mbfmt->height = geo.output.height;
+ ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
+ set_fmt, NULL, &format);
/* Must be implemented, so, don't check for -ENOIOCTLCMD */
if (ret < 0)
return ret;
dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__,
- geo.output.width, geo.output.height, mbfmt.width, mbfmt.height);
+ geo.output.width, geo.output.height, mbfmt->width, mbfmt->height);
/* Sanity checks */
- if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
- (unsigned)mbfmt.height > img_height_max ||
- mbfmt.code != MEDIA_BUS_FMT_YUYV8_2X8)
+ if ((unsigned)mbfmt->width > VOU_MAX_IMAGE_WIDTH ||
+ (unsigned)mbfmt->height > img_height_max ||
+ mbfmt->code != MEDIA_BUS_FMT_YUYV8_2X8)
return -EIO;
- if (mbfmt.width != geo.output.width ||
- mbfmt.height != geo.output.height) {
- geo.output.width = mbfmt.width;
- geo.output.height = mbfmt.height;
+ if (mbfmt->width != geo.output.width ||
+ mbfmt->height != geo.output.height) {
+ geo.output.width = mbfmt->width;
+ geo.output.height = mbfmt->height;
vou_adjust_input(&geo, vou_dev->std);
}
struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
struct v4l2_pix_format *pix = &vou_dev->pix;
struct sh_vou_geometry geo;
- struct v4l2_mbus_framefmt mbfmt = {
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
/* Revisit: is this the correct code? */
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
- .field = V4L2_FIELD_INTERLACED,
- .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ .format.code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .format.field = V4L2_FIELD_INTERLACED,
+ .format.colorspace = V4L2_COLORSPACE_SMPTE170M,
};
unsigned int img_height_max;
int ret;
*/
v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
s_crop, &sd_crop);
- mbfmt.width = geo.output.width;
- mbfmt.height = geo.output.height;
- ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
- s_mbus_fmt, &mbfmt);
+ format.format.width = geo.output.width;
+ format.format.height = geo.output.height;
+ ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
+ set_fmt, NULL, &format);
/* Must be implemented, so, don't check for -ENOIOCTLCMD */
if (ret < 0)
return ret;
/* Sanity checks */
- if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
- (unsigned)mbfmt.height > img_height_max ||
- mbfmt.code != MEDIA_BUS_FMT_YUYV8_2X8)
+ if ((unsigned)format.format.width > VOU_MAX_IMAGE_WIDTH ||
+ (unsigned)format.format.height > img_height_max ||
+ format.format.code != MEDIA_BUS_FMT_YUYV8_2X8)
return -EIO;
- geo.output.width = mbfmt.width;
- geo.output.height = mbfmt.height;
+ geo.output.width = format.format.width;
+ geo.output.height = format.format.height;
/*
* No down-scaling. According to the API, current call has precedence:
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
dev_dbg(icd->parent, "Plan to set format %dx%d\n",
pix->width, pix->height);
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
if (ret < 0)
return ret;
- if (mf.code != xlate->code)
+ if (mf->code != xlate->code)
return -EINVAL;
ret = configure_geometry(isi, pix->width, pix->height, xlate->code);
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
icd->current_fmt = xlate;
dev_dbg(icd->parent, "Finally set format %dx%d\n",
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
u32 pixfmt = pix->pixelformat;
int ret;
pix->width = MAX_SUPPORT_WIDTH;
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->colorspace = mf->colorspace;
- switch (mf.field) {
+ switch (mf->field) {
case V4L2_FIELD_ANY:
pix->field = V4L2_FIELD_NONE;
break;
break;
default:
dev_err(icd->parent, "Field type %d unsupported.\n",
- mf.field);
+ mf->field);
ret = -EINVAL;
}
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int formats = 0, ret;
/* sensor format */
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
/* soc camera host format */
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
/* No more formats */
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
dev_err(icd->parent,
- "Invalid format code #%u: %d\n", idx, code);
+ "Invalid format code #%u: %d\n", idx, code.code);
return 0;
}
return 0;
}
- switch (code) {
+ switch (code.code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
case MEDIA_BUS_FMT_YUYV8_2X8:
formats++;
if (xlate) {
xlate->host_fmt = &isi_camera_formats[0];
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(icd->parent, "Providing format %s using code %d\n",
- isi_camera_formats[0].name, code);
+ isi_camera_formats[0].name, code.code);
}
break;
default:
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
}
struct v4l2_crop a_writable = *a;
struct v4l2_rect *rect = &a_writable.c;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
int ret;
soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
return ret;
/* The capture device might have changed its output */
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
dev_dbg(icd->parent, "Sensor cropped %dx%d\n",
- mf.width, mf.height);
+ mf->width, mf->height);
- icd->user_width = mf.width;
- icd->user_height = mf.height;
+ icd->user_width = mf->width;
+ icd->user_height = mf->height;
return ret;
}
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_mbus_pixelfmt *fmt;
struct device *dev = icd->parent;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
int ret, formats = 0;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
/* no more formats */
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
- dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
+ dev_err(dev, "Invalid format code #%u: %d\n", idx, code.code);
return 0;
}
- if (code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (code.code == MEDIA_BUS_FMT_YUYV8_2X8 ||
+ code.code == MEDIA_BUS_FMT_UYVY8_2X8) {
formats++;
if (xlate) {
/*
*/
xlate->host_fmt =
soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_1_5X8);
- xlate->code = code;
+ xlate->code = code.code;
dev_dbg(dev, "Providing host format %s for sensor code %d\n",
- xlate->host_fmt->name, code);
+ xlate->host_fmt->name, code.code);
xlate++;
}
}
- if (code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (code.code == MEDIA_BUS_FMT_UYVY8_2X8) {
formats++;
if (xlate) {
xlate->host_fmt =
soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_2X8);
- xlate->code = code;
+ xlate->code = code.code;
dev_dbg(dev, "Providing host format %s for sensor code %d\n",
- xlate->host_fmt->name, code);
+ xlate->host_fmt->name, code.code);
xlate++;
}
}
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
}
return formats;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n",
return -EINVAL;
}
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
/* Store width and height returned by the sensor for resizing */
- pcdev->s_width = mf.width;
- pcdev->s_height = mf.height;
+ pcdev->s_width = mf->width;
+ pcdev->s_height = mf->height;
dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n",
__func__, pcdev->s_width, pcdev->s_height);
xlate->host_fmt->fourcc);
memset(pcdev->resizing, 0, sizeof(pcdev->resizing));
- if ((mf.width != pix->width || mf.height != pix->height) &&
+ if ((mf->width != pix->width || mf->height != pix->height) &&
pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
- if (mx2_emmaprp_resize(pcdev, &mf, pix, true) < 0)
+ if (mx2_emmaprp_resize(pcdev, mf, pix, true) < 0)
dev_dbg(icd->parent, "%s: can't resize\n", __func__);
}
- if (mf.code != xlate->code)
+ if (mf->code != xlate->code)
return -EINVAL;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
icd->current_fmt = xlate;
dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n",
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
__u32 pixfmt = pix->pixelformat;
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx2_camera_dev *pcdev = ici->priv;
pix->width &= ~0x7;
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
emma_prp = mx27_emma_prp_get_format(xlate->code,
xlate->host_fmt->fourcc);
- if ((mf.width != pix->width || mf.height != pix->height) &&
+ if ((mf->width != pix->width || mf->height != pix->height) &&
emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) {
- if (mx2_emmaprp_resize(pcdev, &mf, pix, false) < 0)
+ if (mx2_emmaprp_resize(pcdev, mf, pix, false) < 0)
dev_dbg(icd->parent, "%s: can't resize\n", __func__);
}
- if (mf.field == V4L2_FIELD_ANY)
- mf.field = V4L2_FIELD_NONE;
+ if (mf->field == V4L2_FIELD_ANY)
+ mf->field = V4L2_FIELD_NONE;
/*
* Driver supports interlaced images provided they have
* both fields so that they can be processed as if they
* were progressive.
*/
- if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) {
+ if (mf->field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf->field)) {
dev_err(icd->parent, "Field type %d unsupported.\n",
- mf.field);
+ mf->field);
return -EINVAL;
}
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n",
__func__, pix->width, pix->height);
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
int formats = 0, ret;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
/* No more formats */
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
dev_warn(icd->parent,
- "Unsupported format code #%u: 0x%x\n", idx, code);
+ "Unsupported format code #%u: 0x%x\n", idx, code.code);
return 0;
}
if (ret < 0)
return 0;
- switch (code) {
+ switch (code.code) {
case MEDIA_BUS_FMT_SBGGR10_1X10:
formats++;
if (xlate) {
xlate->host_fmt = &mx3_camera_formats[0];
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(dev, "Providing format %s using code 0x%x\n",
- mx3_camera_formats[0].name, code);
+ mx3_camera_formats[0].name, code.code);
}
break;
case MEDIA_BUS_FMT_Y10_1X10:
formats++;
if (xlate) {
xlate->host_fmt = &mx3_camera_formats[1];
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(dev, "Providing format %s using code 0x%x\n",
- mx3_camera_formats[1].name, code);
+ mx3_camera_formats[1].name, code.code);
}
break;
default:
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n",
(fmt->fourcc >> (0*8)) & 0xFF,
(fmt->fourcc >> (1*8)) & 0xFF,
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
int ret;
soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
return ret;
/* The capture device might have changed its output sizes */
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
- if (mf.code != icd->current_fmt->code)
+ if (mf->code != icd->current_fmt->code)
return -EINVAL;
- if (mf.width & 7) {
+ if (mf->width & 7) {
/* Ouch! We can only handle 8-byte aligned width... */
- stride_align(&mf.width);
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ stride_align(&mf->width);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt);
if (ret < 0)
return ret;
}
- if (mf.width != icd->user_width || mf.height != icd->user_height)
- configure_geometry(mx3_cam, mf.width, mf.height,
+ if (mf->width != icd->user_width || mf->height != icd->user_height)
+ configure_geometry(mx3_cam, mf->width, mf->height,
icd->current_fmt->host_fmt);
dev_dbg(icd->parent, "Sensor cropped %dx%d\n",
- mf.width, mf.height);
+ mf->width, mf->height);
- icd->user_width = mf.width;
- icd->user_height = mf.height;
+ icd->user_width = mf->width;
+ icd->user_height = mf->height;
return ret;
}
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
configure_geometry(mx3_cam, pix->width, pix->height, xlate->host_fmt);
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
if (ret < 0)
return ret;
- if (mf.code != xlate->code)
+ if (mf->code != xlate->code)
return -EINVAL;
if (!mx3_cam->idmac_channel[0]) {
return ret;
}
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- mx3_cam->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ mx3_cam->field = mf->field;
+ pix->colorspace = mf->colorspace;
icd->current_fmt = xlate;
dev_dbg(icd->parent, "Sensor set %dx%d\n", pix->width, pix->height);
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
__u32 pixfmt = pix->pixelformat;
int ret;
pix->width = 4096;
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->colorspace = mf->colorspace;
- switch (mf.field) {
+ switch (mf->field) {
case V4L2_FIELD_ANY:
pix->field = V4L2_FIELD_NONE;
break;
break;
default:
dev_err(icd->parent, "Field type %d unsupported.\n",
- mf.field);
+ mf->field);
ret = -EINVAL;
}
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
int formats = 0, ret;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
/* No more formats */
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__,
- idx, code);
+ idx, code.code);
return 0;
}
if (fmt->bits_per_sample != 8)
return 0;
- switch (code) {
+ switch (code.code) {
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
formats++;
if (xlate) {
- xlate->host_fmt = soc_mbus_find_fmtdesc(code,
+ xlate->host_fmt = soc_mbus_find_fmtdesc(code.code,
omap1_cam_formats,
ARRAY_SIZE(omap1_cam_formats));
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(dev,
"%s: providing format %s as byte swapped code #%d\n",
- __func__, xlate->host_fmt->name, code);
+ __func__, xlate->host_fmt->name, code.code);
}
default:
if (xlate)
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
}
return 1;
}
-#define subdev_call_with_sense(pcdev, dev, icd, sd, function, args...) \
+#define subdev_call_with_sense(pcdev, dev, icd, sd, op, function, args...) \
({ \
struct soc_camera_sense sense = { \
.master_clock = pcdev->camexclk, \
if (pcdev->pdata) \
sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \
icd->sense = &sense; \
- __ret = v4l2_subdev_call(sd, video, function, ##args); \
+ __ret = v4l2_subdev_call(sd, op, function, ##args); \
icd->sense = NULL; \
\
if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { \
__ret; \
})
-static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
+static int set_format(struct omap1_cam_dev *pcdev, struct device *dev,
struct soc_camera_device *icd, struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf,
+ struct v4l2_subdev_format *format,
const struct soc_camera_format_xlate *xlate)
{
s32 bytes_per_line;
- int ret = subdev_call_with_sense(pcdev, dev, icd, sd, s_mbus_fmt, mf);
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ int ret = subdev_call_with_sense(pcdev, dev, icd, sd, pad, set_fmt, NULL, format);
if (ret < 0) {
- dev_err(dev, "%s: s_mbus_fmt failed\n", __func__);
+ dev_err(dev, "%s: set_fmt failed\n", __func__);
return ret;
}
struct device *dev = icd->parent;
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct omap1_cam_dev *pcdev = ici->priv;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
int ret;
- ret = subdev_call_with_sense(pcdev, dev, icd, sd, s_crop, crop);
+ ret = subdev_call_with_sense(pcdev, dev, icd, sd, video, s_crop, crop);
if (ret < 0) {
dev_warn(dev, "%s: failed to crop to %ux%u@%u:%u\n", __func__,
rect->width, rect->height, rect->left, rect->top);
return ret;
}
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0) {
dev_warn(dev, "%s: failed to fetch current format\n", __func__);
return ret;
}
- ret = dma_align(&mf.width, &mf.height, xlate->host_fmt, pcdev->vb_mode,
+ ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode,
false);
if (ret < 0) {
dev_err(dev, "%s: failed to align %ux%u %s with DMA\n",
- __func__, mf.width, mf.height,
+ __func__, mf->width, mf->height,
xlate->host_fmt->name);
return ret;
}
if (!ret) {
/* sensor returned geometry not DMA aligned, trying to fix */
- ret = set_mbus_format(pcdev, dev, icd, sd, &mf, xlate);
+ ret = set_format(pcdev, dev, icd, sd, &fmt, xlate);
if (ret < 0) {
dev_err(dev, "%s: failed to set format\n", __func__);
return ret;
}
}
- icd->user_width = mf.width;
- icd->user_height = mf.height;
+ icd->user_width = mf->width;
+ icd->user_height = mf->height;
return 0;
}
struct soc_camera_host *ici = to_soc_camera_host(dev);
struct omap1_cam_dev *pcdev = ici->priv;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
return -EINVAL;
}
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = dma_align(&mf.width, &mf.height, xlate->host_fmt, pcdev->vb_mode,
+ ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode,
true);
if (ret < 0) {
dev_err(dev, "%s: failed to align %ux%u %s with DMA\n",
return ret;
}
- ret = set_mbus_format(pcdev, dev, icd, sd, &mf, xlate);
+ ret = set_format(pcdev, dev, icd, sd, &format, xlate);
if (ret < 0) {
dev_err(dev, "%s: failed to set format\n", __func__);
return ret;
}
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
icd->current_fmt = xlate;
return 0;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
/* TODO: limit to mx1 hardware capabilities */
return -EINVAL;
}
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
/* limit to sensor capabilities */
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
return 0;
}
struct device *dev = icd->parent;
int formats = 0, ret;
struct pxa_cam *cam;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
/* No more formats */
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
- dev_err(dev, "Invalid format code #%u: %d\n", idx, code);
+ dev_err(dev, "Invalid format code #%u: %d\n", idx, code.code);
return 0;
}
cam = icd->host_priv;
}
- switch (code) {
+ switch (code.code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
formats++;
if (xlate) {
xlate->host_fmt = &pxa_camera_formats[0];
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(dev, "Providing format %s using code %d\n",
- pxa_camera_formats[0].name, code);
+ pxa_camera_formats[0].name, code.code);
}
case MEDIA_BUS_FMT_VYUY8_2X8:
case MEDIA_BUS_FMT_YUYV8_2X8:
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
}
.master_clock = pcdev->mclk,
.pixel_clock_max = pcdev->ciclk / 4,
};
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
struct pxa_cam *cam = icd->host_priv;
u32 fourcc = icd->current_fmt->host_fmt->fourcc;
int ret;
return ret;
}
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
- if (pxa_camera_check_frame(mf.width, mf.height)) {
+ if (pxa_camera_check_frame(mf->width, mf->height)) {
/*
* Camera cropping produced a frame beyond our capabilities.
* FIXME: just extract a subframe, that we can process.
*/
- v4l_bound_align_image(&mf.width, 48, 2048, 1,
- &mf.height, 32, 2048, 0,
+ v4l_bound_align_image(&mf->width, 48, 2048, 1,
+ &mf->height, 32, 2048, 0,
fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0);
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt);
if (ret < 0)
return ret;
- if (pxa_camera_check_frame(mf.width, mf.height)) {
+ if (pxa_camera_check_frame(mf->width, mf->height)) {
dev_warn(icd->parent,
"Inconsistent state. Use S_FMT to repair\n");
return -EINVAL;
recalculate_fifo_timeout(pcdev, sense.pixel_clock);
}
- icd->user_width = mf.width;
- icd->user_height = mf.height;
+ icd->user_width = mf->width;
+ icd->user_height = mf->height;
pxa_camera_setup_cicr(icd, cam->flags, fourcc);
.pixel_clock_max = pcdev->ciclk / 4,
};
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
int ret;
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
/* The caller holds a mutex. */
icd->sense = &sense;
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format);
- if (mf.code != xlate->code)
+ if (mf->code != xlate->code)
return -EINVAL;
icd->sense = NULL;
if (ret < 0) {
dev_warn(dev, "Failed to configure for format %x\n",
pix->pixelformat);
- } else if (pxa_camera_check_frame(mf.width, mf.height)) {
+ } else if (pxa_camera_check_frame(mf->width, mf->height)) {
dev_warn(dev,
"Camera driver produced an unsupported frame %dx%d\n",
- mf.width, mf.height);
+ mf->width, mf->height);
ret = -EINVAL;
} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
if (sense.pixel_clock > sense.pixel_clock_max) {
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
icd->current_fmt = xlate;
return ret;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
__u32 pixfmt = pix->pixelformat;
int ret;
pixfmt == V4L2_PIX_FMT_YUV422P ? 4 : 0);
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
+ mf->width = pix->width;
+ mf->height = pix->height;
/* Only progressive video supported so far */
- mf.field = V4L2_FIELD_NONE;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
+ mf->field = V4L2_FIELD_NONE;
+ mf->colorspace = pix->colorspace;
+ mf->code = xlate->code;
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->colorspace = mf->colorspace;
- switch (mf.field) {
+ switch (mf->field) {
case V4L2_FIELD_ANY:
case V4L2_FIELD_NONE:
pix->field = V4L2_FIELD_NONE;
default:
/* TODO: support interlaced at least in pass-through mode */
dev_err(icd->parent, "Field type %d unsupported.\n",
- mf.field);
+ mf->field);
return -EINVAL;
}
int ret, k, n;
int formats = 0;
struct rcar_vin_cam *cam;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
- dev_warn(dev, "unsupported format code #%u: %d\n", idx, code);
+ dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
return 0;
}
return 0;
if (!icd->host_priv) {
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
struct v4l2_rect rect;
struct device *dev = icd->parent;
int shift;
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
/* Sensor driver doesn't support cropping */
rect.left = 0;
rect.top = 0;
- rect.width = mf.width;
- rect.height = mf.height;
+ rect.width = mf->width;
+ rect.height = mf->height;
} else if (ret < 0) {
return ret;
}
* 1280x960, 640x480, 320x240
*/
for (shift = 0; shift < 3; shift++) {
- if (mf.width <= VIN_MAX_WIDTH &&
- mf.height <= VIN_MAX_HEIGHT)
+ if (mf->width <= VIN_MAX_WIDTH &&
+ mf->height <= VIN_MAX_HEIGHT)
break;
- mf.width = 1280 >> shift;
- mf.height = 960 >> shift;
+ mf->width = 1280 >> shift;
+ mf->height = 960 >> shift;
ret = v4l2_device_call_until_err(sd->v4l2_dev,
soc_camera_grp_id(icd),
- video, s_mbus_fmt,
- &mf);
+ pad, set_fmt, NULL,
+ &fmt);
if (ret < 0)
return ret;
}
if (shift == 3) {
dev_err(dev,
"Failed to configure the client below %ux%u\n",
- mf.width, mf.height);
+ mf->width, mf->height);
return -EIO;
}
- dev_dbg(dev, "camera fmt %ux%u\n", mf.width, mf.height);
+ dev_dbg(dev, "camera fmt %ux%u\n", mf->width, mf->height);
cam = kzalloc(sizeof(*cam), GFP_KERNEL);
if (!cam)
*/
cam->rect = rect;
cam->subrect = rect;
- cam->width = mf.width;
- cam->height = mf.height;
- cam->out_width = mf.width;
- cam->out_height = mf.height;
+ cam->width = mf->width;
+ cam->height = mf->height;
+ cam->out_width = mf->width;
+ cam->out_height = mf->height;
icd->host_priv = cam;
} else {
if (!idx)
cam->extra_fmt = NULL;
- switch (code) {
+ switch (code.code) {
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YUYV10_2X10:
formats += n;
for (k = 0; xlate && k < n; k++, xlate++) {
xlate->host_fmt = &rcar_vin_formats[k];
- xlate->code = code;
+ xlate->code = code.code;
dev_dbg(dev, "Providing format %s using code %d\n",
- rcar_vin_formats[k].name, code);
+ rcar_vin_formats[k].name, code.code);
}
break;
default:
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
}
struct v4l2_rect *cam_rect = &cam_crop.c;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
u32 vnmc;
int ret, i;
/* On success cam_crop contains current camera crop */
/* Retrieve camera output window */
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
- if (mf.width > VIN_MAX_WIDTH || mf.height > VIN_MAX_HEIGHT)
+ if (mf->width > VIN_MAX_WIDTH || mf->height > VIN_MAX_HEIGHT)
return -EINVAL;
/* Cache camera output window */
- cam->width = mf.width;
- cam->height = mf.height;
+ cam->width = mf->width;
+ cam->height = mf->height;
icd->user_width = cam->width;
icd->user_height = cam->height;
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
__u32 pixfmt = pix->pixelformat;
int width, height;
int ret;
pix->sizeimage = 0;
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.code = xlate->code;
- mf.colorspace = pix->colorspace;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->code = xlate->code;
+ mf->colorspace = pix->colorspace;
ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
- video, try_mbus_fmt, &mf);
+ pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
/* Adjust only if VIN cannot scale */
- if (pix->width > mf.width * 2)
- pix->width = mf.width * 2;
- if (pix->height > mf.height * 3)
- pix->height = mf.height * 3;
+ if (pix->width > mf->width * 2)
+ pix->width = mf->width * 2;
+ if (pix->height > mf->height * 3)
+ pix->height = mf->height * 3;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
if (pixfmt == V4L2_PIX_FMT_NV16) {
/* FIXME: check against rect_max after converting soc-camera */
* requested a bigger rectangle, it will not return a
* smaller one.
*/
- mf.width = VIN_MAX_WIDTH;
- mf.height = VIN_MAX_HEIGHT;
+ mf->width = VIN_MAX_WIDTH;
+ mf->height = VIN_MAX_HEIGHT;
ret = v4l2_device_call_until_err(sd->v4l2_dev,
soc_camera_grp_id(icd),
- video, try_mbus_fmt,
- &mf);
+ pad, set_fmt, &pad_cfg,
+ &format);
if (ret < 0) {
dev_err(icd->parent,
"client try_fmt() = %d\n", ret);
}
}
/* We will scale exactly */
- if (mf.width > width)
+ if (mf->width > width)
pix->width = width;
- if (mf.height > height)
+ if (mf->height > height)
pix->height = height;
}
int ret, k, n;
int formats = 0;
struct sh_mobile_ceu_cam *cam;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .index = idx,
+ };
const struct soc_mbus_pixelfmt *fmt;
- ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+ ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0)
/* No more formats */
return 0;
- fmt = soc_mbus_get_fmtdesc(code);
+ fmt = soc_mbus_get_fmtdesc(code.code);
if (!fmt) {
- dev_warn(dev, "unsupported format code #%u: %d\n", idx, code);
+ dev_warn(dev, "unsupported format code #%u: %d\n", idx, code.code);
return 0;
}
}
if (!icd->host_priv) {
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
struct v4l2_rect rect;
int shift = 0;
return ret;
/* First time */
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
* sizes, just try VGA multiples. If needed, this can be
* adjusted in the future.
*/
- while ((mf.width > pcdev->max_width ||
- mf.height > pcdev->max_height) && shift < 4) {
+ while ((mf->width > pcdev->max_width ||
+ mf->height > pcdev->max_height) && shift < 4) {
/* Try 2560x1920, 1280x960, 640x480, 320x240 */
- mf.width = 2560 >> shift;
- mf.height = 1920 >> shift;
+ mf->width = 2560 >> shift;
+ mf->height = 1920 >> shift;
ret = v4l2_device_call_until_err(sd->v4l2_dev,
- soc_camera_grp_id(icd), video,
- s_mbus_fmt, &mf);
+ soc_camera_grp_id(icd), pad,
+ set_fmt, NULL, &fmt);
if (ret < 0)
return ret;
shift++;
if (shift == 4) {
dev_err(dev, "Failed to configure the client below %ux%x\n",
- mf.width, mf.height);
+ mf->width, mf->height);
return -EIO;
}
- dev_geo(dev, "camera fmt %ux%u\n", mf.width, mf.height);
+ dev_geo(dev, "camera fmt %ux%u\n", mf->width, mf->height);
cam = kzalloc(sizeof(*cam), GFP_KERNEL);
if (!cam)
cam->rect = rect;
cam->subrect = rect;
- cam->width = mf.width;
- cam->height = mf.height;
+ cam->width = mf->width;
+ cam->height = mf->height;
icd->host_priv = cam;
} else {
if (!idx)
cam->extra_fmt = NULL;
- switch (code) {
+ switch (code.code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
case MEDIA_BUS_FMT_YUYV8_2X8:
formats += n;
for (k = 0; xlate && k < n; k++) {
xlate->host_fmt = &sh_mobile_ceu_formats[k];
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(dev, "Providing format %s using code %d\n",
- sh_mobile_ceu_formats[k].name, code);
+ sh_mobile_ceu_formats[k].name, code.code);
}
break;
default:
formats++;
if (xlate) {
xlate->host_fmt = fmt;
- xlate->code = code;
+ xlate->code = code.code;
xlate++;
dev_dbg(dev, "Providing format %s in pass-through mode\n",
fmt->name);
struct sh_mobile_ceu_cam *cam = icd->host_priv;
struct v4l2_rect *cam_rect = &cam_crop.c;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v,
out_width, out_height;
int interm_width, interm_height;
/* On success cam_crop contains current camera crop */
/* 3. Retrieve camera output window */
- ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt);
if (ret < 0)
return ret;
- if (mf.width > pcdev->max_width || mf.height > pcdev->max_height)
+ if (mf->width > pcdev->max_width || mf->height > pcdev->max_height)
return -EINVAL;
/* 4. Calculate camera scales */
- scale_cam_h = calc_generic_scale(cam_rect->width, mf.width);
- scale_cam_v = calc_generic_scale(cam_rect->height, mf.height);
+ scale_cam_h = calc_generic_scale(cam_rect->width, mf->width);
+ scale_cam_v = calc_generic_scale(cam_rect->height, mf->height);
/* Calculate intermediate window */
interm_width = scale_down(rect->width, scale_cam_h);
new_scale_h = calc_generic_scale(rect->width, icd->user_width);
- mf.width = scale_down(cam_rect->width, new_scale_h);
+ mf->width = scale_down(cam_rect->width, new_scale_h);
}
if (interm_height < icd->user_height) {
new_scale_v = calc_generic_scale(rect->height, icd->user_height);
- mf.height = scale_down(cam_rect->height, new_scale_v);
+ mf->height = scale_down(cam_rect->height, new_scale_v);
}
if (interm_width < icd->user_width || interm_height < icd->user_height) {
ret = v4l2_device_call_until_err(sd->v4l2_dev,
- soc_camera_grp_id(icd), video,
- s_mbus_fmt, &mf);
+ soc_camera_grp_id(icd), pad,
+ set_fmt, NULL, &fmt);
if (ret < 0)
return ret;
- dev_geo(dev, "New camera output %ux%u\n", mf.width, mf.height);
- scale_cam_h = calc_generic_scale(cam_rect->width, mf.width);
- scale_cam_v = calc_generic_scale(cam_rect->height, mf.height);
+ dev_geo(dev, "New camera output %ux%u\n", mf->width, mf->height);
+ scale_cam_h = calc_generic_scale(cam_rect->width, mf->width);
+ scale_cam_v = calc_generic_scale(cam_rect->height, mf->height);
interm_width = scale_down(rect->width, scale_cam_h);
interm_height = scale_down(rect->height, scale_cam_v);
}
/* Cache camera output window */
- cam->width = mf.width;
- cam->height = mf.height;
+ cam->width = mf->width;
+ cam->height = mf->height;
if (pcdev->image_mode) {
out_width = min(interm_width, icd->user_width);
const struct soc_camera_format_xlate *xlate;
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
+ struct v4l2_mbus_framefmt *mf = &format.format;
__u32 pixfmt = pix->pixelformat;
int width, height;
int ret;
height = pix->height;
/* limit to sensor capabilities */
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.code = xlate->code;
- mf.colorspace = pix->colorspace;
+ mf->width = pix->width;
+ mf->height = pix->height;
+ mf->field = pix->field;
+ mf->code = xlate->code;
+ mf->colorspace = pix->colorspace;
ret = v4l2_device_call_until_err(sd->v4l2_dev, soc_camera_grp_id(icd),
- video, try_mbus_fmt, &mf);
+ pad, set_fmt, &pad_cfg, &format);
if (ret < 0)
return ret;
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
+ pix->width = mf->width;
+ pix->height = mf->height;
+ pix->field = mf->field;
+ pix->colorspace = mf->colorspace;
switch (pixfmt) {
case V4L2_PIX_FMT_NV12:
* requested a bigger rectangle, it will not return a
* smaller one.
*/
- mf.width = pcdev->max_width;
- mf.height = pcdev->max_height;
+ mf->width = pcdev->max_width;
+ mf->height = pcdev->max_height;
ret = v4l2_device_call_until_err(sd->v4l2_dev,
- soc_camera_grp_id(icd), video,
- try_mbus_fmt, &mf);
+ soc_camera_grp_id(icd), pad,
+ set_fmt, &pad_cfg, &format);
if (ret < 0) {
/* Shouldn't actually happen... */
dev_err(icd->parent,
}
}
/* We will scale exactly */
- if (mf.width > width)
+ if (mf->width > width)
pix->width = width;
- if (mf.height > height)
+ if (mf->height > height)
pix->height = height;
pix->bytesperline = max(pix->bytesperline, pix->width);
static void sh_csi2_hwinit(struct sh_csi2 *priv);
-static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+static int sh_csi2_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev);
struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data;
+ struct v4l2_mbus_framefmt *mf = &format->format;
+ u32 tmp = (priv->client->channel & 3) << 8;
+
+ if (format->pad)
+ return -EINVAL;
if (mf->width > 8188)
mf->width = 8188;
break;
}
- return 0;
-}
-
-/*
- * We have done our best in try_fmt to try and tell the sensor, which formats
- * we support. If now the configuration is unsuitable for us we can only
- * error out.
- */
-static int sh_csi2_s_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- struct sh_csi2 *priv = container_of(sd, struct sh_csi2, subdev);
- u32 tmp = (priv->client->channel & 3) << 8;
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+ cfg->try_fmt = *mf;
+ return 0;
+ }
- dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
if (mf->width > 8188 || mf->width & 1)
return -EINVAL;
}
static struct v4l2_subdev_video_ops sh_csi2_subdev_video_ops = {
- .s_mbus_fmt = sh_csi2_s_fmt,
- .try_mbus_fmt = sh_csi2_try_fmt,
.g_mbus_config = sh_csi2_g_mbus_config,
.s_mbus_config = sh_csi2_s_mbus_config,
};
+static struct v4l2_subdev_pad_ops sh_csi2_subdev_pad_ops = {
+ .set_fmt = sh_csi2_set_fmt,
+};
+
static void sh_csi2_hwinit(struct sh_csi2 *priv)
{
struct sh_csi2_pdata *pdata = priv->pdev->dev.platform_data;
static struct v4l2_subdev_ops sh_csi2_subdev_ops = {
.core = &sh_csi2_subdev_core_ops,
.video = &sh_csi2_subdev_video_ops,
+ .pad = &sh_csi2_subdev_pad_ops,
};
static int sh_csi2_probe(struct platform_device *pdev)
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
unsigned int i, fmts = 0, raw_fmts = 0;
int ret;
- u32 code;
+ struct v4l2_subdev_mbus_code_enum code = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
- while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
+ while (!v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code)) {
raw_fmts++;
+ code.index++;
+ }
if (!ici->ops->get_formats)
/*
fmts = 0;
for (i = 0; i < raw_fmts; i++)
if (!ici->ops->get_formats) {
- v4l2_subdev_call(sd, video, enum_mbus_fmt, i, &code);
+ code.index = i;
+ v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
icd->user_formats[fmts].host_fmt =
- soc_mbus_get_fmtdesc(code);
+ soc_mbus_get_fmtdesc(code.code);
if (icd->user_formats[fmts].host_fmt)
- icd->user_formats[fmts++].code = code;
+ icd->user_formats[fmts++].code = code.code;
} else {
ret = ici->ops->get_formats(icd, i,
&icd->user_formats[fmts]);
static int soc_camera_probe_finish(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct v4l2_mbus_framefmt mf;
+ struct v4l2_subdev_format fmt = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+ struct v4l2_mbus_framefmt *mf = &fmt.format;
int ret;
sd->grp_id = soc_camera_grp_id(icd);
goto evidstart;
/* Try to improve our guess of a reasonable window format */
- if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
- icd->user_width = mf.width;
- icd->user_height = mf.height;
- icd->colorspace = mf.colorspace;
- icd->field = mf.field;
+ if (!v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt)) {
+ icd->user_width = mf->width;
+ icd->user_height = mf->height;
+ icd->colorspace = mf->colorspace;
+ icd->field = mf->field;
}
soc_camera_remove_device(icd);
}
static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
+ struct v4l2_mbus_framefmt *mf = &format->format;
mf->width = p->format.width;
mf->height = p->format.height;
.s_power = soc_camera_platform_s_power,
};
-static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+static int soc_camera_platform_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_mbus_code_enum *code)
{
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
- if (index)
+ if (code->pad || code->index)
return -EINVAL;
- *code = p->format.code;
+ code->code = p->format.code;
return 0;
}
static struct v4l2_subdev_video_ops platform_subdev_video_ops = {
.s_stream = soc_camera_platform_s_stream,
- .enum_mbus_fmt = soc_camera_platform_enum_fmt,
.cropcap = soc_camera_platform_cropcap,
.g_crop = soc_camera_platform_g_crop,
- .try_mbus_fmt = soc_camera_platform_fill_fmt,
- .g_mbus_fmt = soc_camera_platform_fill_fmt,
- .s_mbus_fmt = soc_camera_platform_fill_fmt,
.g_mbus_config = soc_camera_platform_g_mbus_config,
};
+static const struct v4l2_subdev_pad_ops platform_subdev_pad_ops = {
+ .enum_mbus_code = soc_camera_platform_enum_mbus_code,
+ .get_fmt = soc_camera_platform_fill_fmt,
+ .set_fmt = soc_camera_platform_fill_fmt,
+};
+
static struct v4l2_subdev_ops platform_subdev_ops = {
.core = &platform_subdev_core_ops,
.video = &platform_subdev_video_ops,
+ .pad = &platform_subdev_pad_ops,
};
static int soc_camera_platform_probe(struct platform_device *pdev)
}
EXPORT_SYMBOL(soc_camera_client_s_crop);
-/* Iterative s_mbus_fmt, also updates cached client crop on success */
-static int client_s_fmt(struct soc_camera_device *icd,
+/* Iterative set_fmt, also updates cached client crop on success */
+static int client_set_fmt(struct soc_camera_device *icd,
struct v4l2_rect *rect, struct v4l2_rect *subrect,
unsigned int max_width, unsigned int max_height,
- struct v4l2_mbus_framefmt *mf, bool host_can_scale)
+ struct v4l2_subdev_format *format, bool host_can_scale)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
+ struct v4l2_mbus_framefmt *mf = &format->format;
unsigned int width = mf->width, height = mf->height, tmp_w, tmp_h;
struct v4l2_cropcap cap;
bool host_1to1;
int ret;
ret = v4l2_device_call_until_err(sd->v4l2_dev,
- soc_camera_grp_id(icd), video,
- s_mbus_fmt, mf);
+ soc_camera_grp_id(icd), pad,
+ set_fmt, NULL, format);
if (ret < 0)
return ret;
mf->width = tmp_w;
mf->height = tmp_h;
ret = v4l2_device_call_until_err(sd->v4l2_dev,
- soc_camera_grp_id(icd), video,
- s_mbus_fmt, mf);
+ soc_camera_grp_id(icd), pad,
+ set_fmt, NULL, format);
dev_geo(dev, "Camera scaled to %ux%u\n",
mf->width, mf->height);
if (ret < 0) {
bool host_can_scale, unsigned int shift)
{
struct device *dev = icd->parent;
- struct v4l2_mbus_framefmt mf_tmp = *mf;
+ struct v4l2_subdev_format fmt_tmp = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ .format = *mf,
+ };
+ struct v4l2_mbus_framefmt *mf_tmp = &fmt_tmp.format;
unsigned int scale_h, scale_v;
int ret;
* 5. Apply iterative camera S_FMT for camera user window (also updates
* client crop cache and the imaginary sub-rectangle).
*/
- ret = client_s_fmt(icd, rect, subrect, *width, *height,
- &mf_tmp, host_can_scale);
+ ret = client_set_fmt(icd, rect, subrect, *width, *height,
+ &fmt_tmp, host_can_scale);
if (ret < 0)
return ret;
dev_geo(dev, "5: camera scaled to %ux%u\n",
- mf_tmp.width, mf_tmp.height);
+ mf_tmp->width, mf_tmp->height);
/* 6. Retrieve camera output window (g_fmt) */
/* unneeded - it is already in "mf_tmp" */
/* 7. Calculate new client scales. */
- scale_h = soc_camera_calc_scale(rect->width, shift, mf_tmp.width);
- scale_v = soc_camera_calc_scale(rect->height, shift, mf_tmp.height);
+ scale_h = soc_camera_calc_scale(rect->width, shift, mf_tmp->width);
+ scale_v = soc_camera_calc_scale(rect->height, shift, mf_tmp->height);
- mf->width = mf_tmp.width;
- mf->height = mf_tmp.height;
- mf->colorspace = mf_tmp.colorspace;
+ mf->width = mf_tmp->width;
+ mf->height = mf_tmp->height;
+ mf->colorspace = mf_tmp->colorspace;
/*
* 8. Calculate new host crop - apply camera scales to previously
*/
static int viacam_configure_sensor(struct via_camera *cam)
{
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int ret;
- v4l2_fill_mbus_format(&mbus_fmt, &cam->sensor_format, cam->mbus_code);
+ v4l2_fill_mbus_format(&format.format, &cam->sensor_format, cam->mbus_code);
ret = sensor_call(cam, core, init, 0);
if (ret == 0)
- ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt);
+ ret = sensor_call(cam, pad, set_fmt, NULL, &format);
/*
* OV7670 does weird things if flip is set *before* format...
*/
struct v4l2_pix_format *upix, struct v4l2_pix_format *spix)
{
int ret;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_TRY,
+ };
struct via_format *f = via_find_format(upix->pixelformat);
upix->pixelformat = f->pixelformat;
viacam_fmt_pre(upix, spix);
- v4l2_fill_mbus_format(&mbus_fmt, spix, f->mbus_code);
- ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(spix, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, spix, f->mbus_code);
+ ret = sensor_call(cam, pad, set_fmt, &pad_cfg, &format);
+ v4l2_fill_pix_format(spix, &format.format);
viacam_fmt_post(upix, spix);
return ret;
}
};
struct vim2m_fmt {
- char *name;
u32 fourcc;
int depth;
/* Types the format can be used for */
static struct vim2m_fmt formats[] = {
{
- .name = "RGB565 (BE)",
.fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
.depth = 16,
/* Both capture and output format */
.types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
},
{
- .name = "4:2:2, packed, YUYV",
.fourcc = V4L2_PIX_FMT_YUYV,
.depth = 16,
/* Output-only format */
if (i < NUM_FORMATS) {
/* Format found */
fmt = &formats[i];
- strncpy(f->description, fmt->name, sizeof(f->description) - 1);
f->pixelformat = fmt->fourcc;
return 0;
}
return vivid_vid_out_g_parm(file, fh, parm);
}
+static int vidioc_log_status(struct file *file, void *fh)
+{
+ struct vivid_dev *dev = video_drvdata(file);
+ struct video_device *vdev = video_devdata(file);
+
+ v4l2_ctrl_log_status(file, fh);
+ if (vdev->vfl_dir == VFL_DIR_RX && vdev->vfl_type == VFL_TYPE_GRABBER)
+ tpg_log_status(&dev->tpg);
+ return 0;
+}
+
static ssize_t vivid_radio_read(struct file *file, char __user *buf,
size_t size, loff_t *offset)
{
.vidioc_g_edid = vidioc_g_edid,
.vidioc_s_edid = vidioc_s_edid,
- .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_log_status = vidioc_log_status,
.vidioc_subscribe_event = vidioc_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
extern unsigned vivid_debug;
struct vivid_fmt {
- const char *name;
u32 fourcc; /* v4l2 format id */
bool is_yuv;
bool can_do_overlay;
if (dev->radio_rx_freq >= vivid_radio_bands[band].rangelow &&
dev->radio_rx_freq <= vivid_radio_bands[band].rangehigh)
break;
+ if (band == TOT_BANDS)
+ return -EINVAL;
low = vivid_radio_bands[band].rangelow;
high = vivid_radio_bands[band].rangehigh;
}
{ COEFF(-0.116, 224), COEFF(-0.384, 224), COEFF(0.5, 224) },
{ COEFF(0.5, 224), COEFF(-0.445, 224), COEFF(-0.055, 224) },
};
+ static const int smpte240m_full[3][3] = {
+ { COEFF(0.212, 255), COEFF(0.701, 255), COEFF(0.087, 255) },
+ { COEFF(-0.116, 255), COEFF(-0.384, 255), COEFF(0.5, 255) },
+ { COEFF(0.5, 255), COEFF(-0.445, 255), COEFF(-0.055, 255) },
+ };
static const int bt2020[3][3] = {
{ COEFF(0.2627, 219), COEFF(0.6780, 219), COEFF(0.0593, 219) },
{ COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224) },
{ COEFF(0.5, 224), COEFF(-0.4598, 224), COEFF(-0.0402, 224) },
};
+ static const int bt2020_full[3][3] = {
+ { COEFF(0.2627, 255), COEFF(0.6780, 255), COEFF(0.0593, 255) },
+ { COEFF(-0.1396, 255), COEFF(-0.3604, 255), COEFF(0.5, 255) },
+ { COEFF(0.5, 255), COEFF(-0.4698, 255), COEFF(-0.0402, 255) },
+ };
+ static const int bt2020c[4] = {
+ COEFF(1.0 / 1.9404, 224), COEFF(1.0 / 1.5816, 224),
+ COEFF(1.0 / 1.7184, 224), COEFF(1.0 / 0.9936, 224),
+ };
+ static const int bt2020c_full[4] = {
+ COEFF(1.0 / 1.9404, 255), COEFF(1.0 / 1.5816, 255),
+ COEFF(1.0 / 1.7184, 255), COEFF(1.0 / 0.9936, 255),
+ };
+
bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
unsigned y_offset = full ? 0 : 16;
int lin_y, yc;
switch (tpg->real_ycbcr_enc) {
case V4L2_YCBCR_ENC_601:
- case V4L2_YCBCR_ENC_XV601:
case V4L2_YCBCR_ENC_SYCC:
rgb2ycbcr(full ? bt601_full : bt601, r, g, b, y_offset, y, cb, cr);
break;
+ case V4L2_YCBCR_ENC_XV601:
+ /* Ignore quantization range, there is only one possible
+ * Y'CbCr encoding. */
+ rgb2ycbcr(bt601, r, g, b, 16, y, cb, cr);
+ break;
+ case V4L2_YCBCR_ENC_XV709:
+ /* Ignore quantization range, there is only one possible
+ * Y'CbCr encoding. */
+ rgb2ycbcr(rec709, r, g, b, 16, y, cb, cr);
+ break;
case V4L2_YCBCR_ENC_BT2020:
- rgb2ycbcr(bt2020, r, g, b, 16, y, cb, cr);
+ rgb2ycbcr(full ? bt2020_full : bt2020, r, g, b, y_offset, y, cb, cr);
break;
case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
lin_y = (COEFF(0.2627, 255) * rec709_to_linear(r) +
COEFF(0.6780, 255) * rec709_to_linear(g) +
COEFF(0.0593, 255) * rec709_to_linear(b)) >> 16;
yc = linear_to_rec709(lin_y);
- *y = (yc * 219) / 255 + (16 << 4);
+ *y = full ? yc : (yc * 219) / 255 + (16 << 4);
if (b <= yc)
- *cb = (((b - yc) * COEFF(1.0 / 1.9404, 224)) >> 16) + (128 << 4);
+ *cb = (((b - yc) * (full ? bt2020c_full[0] : bt2020c[0])) >> 16) + (128 << 4);
else
- *cb = (((b - yc) * COEFF(1.0 / 1.5816, 224)) >> 16) + (128 << 4);
+ *cb = (((b - yc) * (full ? bt2020c_full[1] : bt2020c[1])) >> 16) + (128 << 4);
if (r <= yc)
- *cr = (((r - yc) * COEFF(1.0 / 1.7184, 224)) >> 16) + (128 << 4);
+ *cr = (((r - yc) * (full ? bt2020c_full[2] : bt2020c[2])) >> 16) + (128 << 4);
else
- *cr = (((r - yc) * COEFF(1.0 / 0.9936, 224)) >> 16) + (128 << 4);
+ *cr = (((r - yc) * (full ? bt2020c_full[3] : bt2020c[3])) >> 16) + (128 << 4);
break;
case V4L2_YCBCR_ENC_SMPTE240M:
- rgb2ycbcr(smpte240m, r, g, b, 16, y, cb, cr);
+ rgb2ycbcr(full ? smpte240m_full : smpte240m, r, g, b, y_offset, y, cb, cr);
break;
case V4L2_YCBCR_ENC_709:
- case V4L2_YCBCR_ENC_XV709:
default:
rgb2ycbcr(full ? rec709_full : rec709, r, g, b, y_offset, y, cb, cr);
break;
{ COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) },
{ COEFF(1, 219), COEFF(1.8270, 224), COEFF(0, 224) },
};
+ static const int smpte240m_full[3][3] = {
+ { COEFF(1, 255), COEFF(0, 255), COEFF(1.5756, 255) },
+ { COEFF(1, 255), COEFF(-0.2253, 255), COEFF(-0.4767, 255) },
+ { COEFF(1, 255), COEFF(1.8270, 255), COEFF(0, 255) },
+ };
static const int bt2020[3][3] = {
{ COEFF(1, 219), COEFF(0, 224), COEFF(1.4746, 224) },
{ COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) },
{ COEFF(1, 219), COEFF(1.8814, 224), COEFF(0, 224) },
};
+ static const int bt2020_full[3][3] = {
+ { COEFF(1, 255), COEFF(0, 255), COEFF(1.4746, 255) },
+ { COEFF(1, 255), COEFF(-0.1646, 255), COEFF(-0.5714, 255) },
+ { COEFF(1, 255), COEFF(1.8814, 255), COEFF(0, 255) },
+ };
+ static const int bt2020c[4] = {
+ COEFF(1.9404, 224), COEFF(1.5816, 224),
+ COEFF(1.7184, 224), COEFF(0.9936, 224),
+ };
+ static const int bt2020c_full[4] = {
+ COEFF(1.9404, 255), COEFF(1.5816, 255),
+ COEFF(1.7184, 255), COEFF(0.9936, 255),
+ };
+
bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
unsigned y_offset = full ? 0 : 16;
+ int y_fac = full ? COEFF(1.0, 255) : COEFF(1.0, 219);
int lin_r, lin_g, lin_b, lin_y;
switch (tpg->real_ycbcr_enc) {
case V4L2_YCBCR_ENC_601:
- case V4L2_YCBCR_ENC_XV601:
case V4L2_YCBCR_ENC_SYCC:
ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, y_offset, r, g, b);
break;
+ case V4L2_YCBCR_ENC_XV601:
+ /* Ignore quantization range, there is only one possible
+ * Y'CbCr encoding. */
+ ycbcr2rgb(bt601, y, cb, cr, 16, r, g, b);
+ break;
+ case V4L2_YCBCR_ENC_XV709:
+ /* Ignore quantization range, there is only one possible
+ * Y'CbCr encoding. */
+ ycbcr2rgb(rec709, y, cb, cr, 16, r, g, b);
+ break;
case V4L2_YCBCR_ENC_BT2020:
- ycbcr2rgb(bt2020, y, cb, cr, 16, r, g, b);
+ ycbcr2rgb(full ? bt2020_full : bt2020, y, cb, cr, y_offset, r, g, b);
break;
case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
- y -= 16 << 4;
+ y -= full ? 0 : 16 << 4;
cb -= 128 << 4;
cr -= 128 << 4;
if (cb <= 0)
- *b = COEFF(1.0, 219) * y + COEFF(1.9404, 224) * cb;
+ *b = y_fac * y + (full ? bt2020c_full[0] : bt2020c[0]) * cb;
else
- *b = COEFF(1.0, 219) * y + COEFF(1.5816, 224) * cb;
+ *b = y_fac * y + (full ? bt2020c_full[1] : bt2020c[1]) * cb;
*b = *b >> 12;
if (cr <= 0)
- *r = COEFF(1.0, 219) * y + COEFF(1.7184, 224) * cr;
+ *r = y_fac * y + (full ? bt2020c_full[2] : bt2020c[2]) * cr;
else
- *r = COEFF(1.0, 219) * y + COEFF(0.9936, 224) * cr;
+ *r = y_fac * y + (full ? bt2020c_full[3] : bt2020c[3]) * cr;
*r = *r >> 12;
lin_r = rec709_to_linear(*r);
lin_b = rec709_to_linear(*b);
- lin_y = rec709_to_linear((y * 255) / 219);
+ lin_y = rec709_to_linear((y * 255) / (full ? 255 : 219));
lin_g = COEFF(1.0 / 0.6780, 255) * lin_y -
COEFF(0.2627 / 0.6780, 255) * lin_r -
*g = linear_to_rec709(lin_g >> 12);
break;
case V4L2_YCBCR_ENC_SMPTE240M:
- ycbcr2rgb(smpte240m, y, cb, cr, 16, r, g, b);
+ ycbcr2rgb(full ? smpte240m_full : smpte240m, y, cb, cr, y_offset, r, g, b);
break;
case V4L2_YCBCR_ENC_709:
- case V4L2_YCBCR_ENC_XV709:
default:
ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, y_offset, r, g, b);
break;
return -1;
}
+void tpg_log_status(struct tpg_data *tpg)
+{
+ pr_info("tpg source WxH: %ux%u (%s)\n",
+ tpg->src_width, tpg->src_height,
+ tpg->is_yuv ? "YCbCr" : "RGB");
+ pr_info("tpg field: %u\n", tpg->field);
+ pr_info("tpg crop: %ux%u@%dx%d\n", tpg->crop.width, tpg->crop.height,
+ tpg->crop.left, tpg->crop.top);
+ pr_info("tpg compose: %ux%u@%dx%d\n", tpg->compose.width, tpg->compose.height,
+ tpg->compose.left, tpg->compose.top);
+ pr_info("tpg colorspace: %d\n", tpg->colorspace);
+ pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc);
+ pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
+ pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
+}
+
/*
* This struct contains common parameters used by both the drawing of the
* test pattern and the drawing of the extras (borders, square, etc.)
void tpg_free(struct tpg_data *tpg);
void tpg_reset_source(struct tpg_data *tpg, unsigned width, unsigned height,
u32 field);
+void tpg_log_status(struct tpg_data *tpg);
void tpg_set_font(const u8 *f);
void tpg_gen_text(const struct tpg_data *tpg,
static const struct vivid_fmt formats_ovl[] = {
{
- .name = "RGB565 (LE)",
.fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "XRGB555 (LE)",
.fourcc = V4L2_PIX_FMT_XRGB555, /* gggbbbbb arrrrrgg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "ARGB555 (LE)",
.fourcc = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
};
/* The number of discrete webcam framesizes */
-#define VIVID_WEBCAM_SIZES 3
+#define VIVID_WEBCAM_SIZES 4
/* The number of discrete webcam frameintervals */
#define VIVID_WEBCAM_IVALS (VIVID_WEBCAM_SIZES * 2)
{ 320, 180 },
{ 640, 360 },
{ 1280, 720 },
+ { 1920, 1080 },
};
/*
* elements in this array as there are in webcam_sizes.
*/
static const struct v4l2_fract webcam_intervals[VIVID_WEBCAM_IVALS] = {
+ { 1, 2 },
+ { 1, 5 },
{ 1, 10 },
{ 1, 15 },
{ 1, 25 },
webcam_sizes[i].height == mp->height)
break;
dev->webcam_size_idx = i;
- if (dev->webcam_ival_idx >= 2 * (3 - i))
- dev->webcam_ival_idx = 2 * (3 - i) - 1;
+ if (dev->webcam_ival_idx >= 2 * (VIVID_WEBCAM_SIZES - i))
+ dev->webcam_ival_idx = 2 * (VIVID_WEBCAM_SIZES - i) - 1;
vivid_update_format_cap(dev, false);
} else {
struct v4l2_rect r = { 0, 0, mp->width, mp->height };
fmt = &formats_ovl[f->index];
- strlcpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
}
break;
if (i == ARRAY_SIZE(webcam_sizes))
return -EINVAL;
- if (fival->index >= 2 * (3 - i))
+ if (fival->index >= 2 * (VIVID_WEBCAM_SIZES - i))
return -EINVAL;
fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
fival->discrete = webcam_intervals[fival->index];
struct v4l2_streamparm *parm)
{
struct vivid_dev *dev = video_drvdata(file);
- unsigned ival_sz = 2 * (3 - dev->webcam_size_idx);
+ unsigned ival_sz = 2 * (VIVID_WEBCAM_SIZES - dev->webcam_size_idx);
struct v4l2_fract tpf;
unsigned i;
struct vivid_fmt vivid_formats[] = {
{
- .name = "4:2:2, packed, YUYV",
.fourcc = V4L2_PIX_FMT_YUYV,
.vdownsampling = { 1 },
.bit_depth = { 16 },
.data_offset = { PLANE0_DATA_OFFSET },
},
{
- .name = "4:2:2, packed, UYVY",
.fourcc = V4L2_PIX_FMT_UYVY,
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "4:2:2, packed, YVYU",
.fourcc = V4L2_PIX_FMT_YVYU,
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "4:2:2, packed, VYUY",
.fourcc = V4L2_PIX_FMT_VYUY,
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "YUV 4:2:2 triplanar",
.fourcc = V4L2_PIX_FMT_YUV422P,
.vdownsampling = { 1, 1, 1 },
.bit_depth = { 8, 4, 4 },
.buffers = 1,
},
{
- .name = "YUV 4:2:0 triplanar",
.fourcc = V4L2_PIX_FMT_YUV420,
.vdownsampling = { 1, 2, 2 },
.bit_depth = { 8, 4, 4 },
.buffers = 1,
},
{
- .name = "YVU 4:2:0 triplanar",
.fourcc = V4L2_PIX_FMT_YVU420,
.vdownsampling = { 1, 2, 2 },
.bit_depth = { 8, 4, 4 },
.buffers = 1,
},
{
- .name = "YUV 4:2:0 biplanar",
.fourcc = V4L2_PIX_FMT_NV12,
.vdownsampling = { 1, 2 },
.bit_depth = { 8, 8 },
.buffers = 1,
},
{
- .name = "YVU 4:2:0 biplanar",
.fourcc = V4L2_PIX_FMT_NV21,
.vdownsampling = { 1, 2 },
.bit_depth = { 8, 8 },
.buffers = 1,
},
{
- .name = "YUV 4:2:2 biplanar",
.fourcc = V4L2_PIX_FMT_NV16,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 8 },
.buffers = 1,
},
{
- .name = "YVU 4:2:2 biplanar",
.fourcc = V4L2_PIX_FMT_NV61,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 8 },
.buffers = 1,
},
{
- .name = "YUV 4:4:4 biplanar",
.fourcc = V4L2_PIX_FMT_NV24,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 16 },
.buffers = 1,
},
{
- .name = "YVU 4:4:4 biplanar",
.fourcc = V4L2_PIX_FMT_NV42,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 16 },
.buffers = 1,
},
{
- .name = "YUV555 (LE)",
.fourcc = V4L2_PIX_FMT_YUV555, /* uuuvvvvv ayyyyyuu */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.alpha_mask = 0x8000,
},
{
- .name = "YUV565 (LE)",
.fourcc = V4L2_PIX_FMT_YUV565, /* uuuvvvvv yyyyyuuu */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "YUV444",
.fourcc = V4L2_PIX_FMT_YUV444, /* uuuuvvvv aaaayyyy */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.alpha_mask = 0xf000,
},
{
- .name = "YUV32 (LE)",
.fourcc = V4L2_PIX_FMT_YUV32, /* ayuv */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.alpha_mask = 0x000000ff,
},
{
- .name = "Monochrome",
.fourcc = V4L2_PIX_FMT_GREY,
.vdownsampling = { 1 },
.bit_depth = { 8 },
.buffers = 1,
},
{
- .name = "RGB332",
.fourcc = V4L2_PIX_FMT_RGB332, /* rrrgggbb */
.vdownsampling = { 1 },
.bit_depth = { 8 },
.buffers = 1,
},
{
- .name = "RGB565 (LE)",
.fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.can_do_overlay = true,
},
{
- .name = "RGB565 (BE)",
.fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.can_do_overlay = true,
},
{
- .name = "RGB444",
.fourcc = V4L2_PIX_FMT_RGB444, /* xxxxrrrr ggggbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "XRGB444",
.fourcc = V4L2_PIX_FMT_XRGB444, /* xxxxrrrr ggggbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "ARGB444",
.fourcc = V4L2_PIX_FMT_ARGB444, /* aaaarrrr ggggbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.alpha_mask = 0x00f0,
},
{
- .name = "RGB555 (LE)",
.fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb xrrrrrgg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.can_do_overlay = true,
},
{
- .name = "XRGB555 (LE)",
.fourcc = V4L2_PIX_FMT_XRGB555, /* gggbbbbb xrrrrrgg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.can_do_overlay = true,
},
{
- .name = "ARGB555 (LE)",
.fourcc = V4L2_PIX_FMT_ARGB555, /* gggbbbbb arrrrrgg */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.alpha_mask = 0x8000,
},
{
- .name = "RGB555 (BE)",
.fourcc = V4L2_PIX_FMT_RGB555X, /* xrrrrrgg gggbbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "XRGB555 (BE)",
.fourcc = V4L2_PIX_FMT_XRGB555X, /* xrrrrrgg gggbbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.buffers = 1,
},
{
- .name = "ARGB555 (BE)",
.fourcc = V4L2_PIX_FMT_ARGB555X, /* arrrrrgg gggbbbbb */
.vdownsampling = { 1 },
.bit_depth = { 16 },
.alpha_mask = 0x0080,
},
{
- .name = "RGB24 (LE)",
.fourcc = V4L2_PIX_FMT_RGB24, /* rgb */
.vdownsampling = { 1 },
.bit_depth = { 24 },
.buffers = 1,
},
{
- .name = "RGB24 (BE)",
.fourcc = V4L2_PIX_FMT_BGR24, /* bgr */
.vdownsampling = { 1 },
.bit_depth = { 24 },
.buffers = 1,
},
{
- .name = "BGR666",
.fourcc = V4L2_PIX_FMT_BGR666, /* bbbbbbgg ggggrrrr rrxxxxxx */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.buffers = 1,
},
{
- .name = "RGB32 (LE)",
.fourcc = V4L2_PIX_FMT_RGB32, /* xrgb */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.buffers = 1,
},
{
- .name = "RGB32 (BE)",
.fourcc = V4L2_PIX_FMT_BGR32, /* bgrx */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.buffers = 1,
},
{
- .name = "XRGB32 (LE)",
.fourcc = V4L2_PIX_FMT_XRGB32, /* xrgb */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.buffers = 1,
},
{
- .name = "XRGB32 (BE)",
.fourcc = V4L2_PIX_FMT_XBGR32, /* bgrx */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.buffers = 1,
},
{
- .name = "ARGB32 (LE)",
.fourcc = V4L2_PIX_FMT_ARGB32, /* argb */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.alpha_mask = 0x000000ff,
},
{
- .name = "ARGB32 (BE)",
.fourcc = V4L2_PIX_FMT_ABGR32, /* bgra */
.vdownsampling = { 1 },
.bit_depth = { 32 },
.alpha_mask = 0xff000000,
},
{
- .name = "Bayer BG/GR",
.fourcc = V4L2_PIX_FMT_SBGGR8, /* Bayer BG/GR */
.vdownsampling = { 1 },
.bit_depth = { 8 },
.buffers = 1,
},
{
- .name = "Bayer GB/RG",
.fourcc = V4L2_PIX_FMT_SGBRG8, /* Bayer GB/RG */
.vdownsampling = { 1 },
.bit_depth = { 8 },
.buffers = 1,
},
{
- .name = "Bayer GR/BG",
.fourcc = V4L2_PIX_FMT_SGRBG8, /* Bayer GR/BG */
.vdownsampling = { 1 },
.bit_depth = { 8 },
.buffers = 1,
},
{
- .name = "Bayer RG/GB",
.fourcc = V4L2_PIX_FMT_SRGGB8, /* Bayer RG/GB */
.vdownsampling = { 1 },
.bit_depth = { 8 },
.buffers = 1,
},
{
- .name = "4:2:2, biplanar, YUV",
.fourcc = V4L2_PIX_FMT_NV16M,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 8 },
.data_offset = { PLANE0_DATA_OFFSET, 0 },
},
{
- .name = "4:2:2, biplanar, YVU",
.fourcc = V4L2_PIX_FMT_NV61M,
.vdownsampling = { 1, 1 },
.bit_depth = { 8, 8 },
.data_offset = { 0, PLANE0_DATA_OFFSET },
},
{
- .name = "4:2:0, triplanar, YUV",
.fourcc = V4L2_PIX_FMT_YUV420M,
.vdownsampling = { 1, 2, 2 },
.bit_depth = { 8, 4, 4 },
.buffers = 3,
},
{
- .name = "4:2:0, triplanar, YVU",
.fourcc = V4L2_PIX_FMT_YVU420M,
.vdownsampling = { 1, 2, 2 },
.bit_depth = { 8, 4, 4 },
.buffers = 3,
},
{
- .name = "4:2:0, biplanar, YUV",
.fourcc = V4L2_PIX_FMT_NV12M,
.vdownsampling = { 1, 2 },
.bit_depth = { 8, 8 },
.buffers = 2,
},
{
- .name = "4:2:0, biplanar, YVU",
.fourcc = V4L2_PIX_FMT_NV21M,
.vdownsampling = { 1, 2 },
.bit_depth = { 8, 8 },
fmt = &vivid_formats[f->index];
- strlcpy(f->description, fmt->name, sizeof(f->description));
f->pixelformat = fmt->fourcc;
return 0;
}
parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
parm->parm.output.timeperframe = dev->timeperframe_vid_out;
parm->parm.output.writebuffers = 1;
-return 0;
+
+ return 0;
}
int vidioc_subscribe_event(struct v4l2_fh *fh,
config VIDEO_XILINX
tristate "Xilinx Video IP (EXPERIMENTAL)"
- depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF
+ depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA
select VIDEOBUF2_DMA_CONTIG
---help---
Driver for Xilinx Video IP Pipelines
err = regcache_sync_region(radio->core->regmap,
SI476X_PROP_DIGITAL_IO_INPUT_SAMPLE_RATE,
SI476X_PROP_DIGITAL_IO_OUTPUT_FORMAT);
- if (err < 0)
- return err;
+ if (err < 0)
+ return err;
err = regcache_sync_region(radio->core->regmap,
SI476X_PROP_AUDIO_DEEMPHASIS,
i2c_get_adapter(pdata->i2c_adapter), pdata->tuner, NULL);
tr->sd_dsp = v4l2_i2c_new_subdev_board(&tr->v4l2_dev,
i2c_get_adapter(pdata->i2c_adapter), pdata->dsp, NULL);
- if (tr->sd_tuner == NULL || tr->sd_dsp == NULL)
+ if (tr->sd_tuner == NULL || tr->sd_dsp == NULL) {
+ err = -ENODEV;
goto err_video_req;
+ }
tr->v4l2_dev.ctrl_handler = tr->sd_dsp->ctrl_handler;
return 0;
si4713_pdev = platform_device_alloc("radio-si4713", -1);
- if (!si4713_pdev)
+ if (!si4713_pdev) {
+ rval = -ENOMEM;
goto put_main_pdev;
+ }
si4713_pdev_pdata.subdev = client;
rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
spinlock_t resp_skb_lock; /* To protect access to received SKB */
long flag; /* FM driver state machine info */
- u8 streg_cbdata; /* status of ST registration */
+ int streg_cbdata; /* status of ST registration */
struct sk_buff_head rx_q; /* RX queue */
struct tasklet_struct rx_task; /* RX Tasklet */
switch (data->count) {
case 12:
- if (!(dev->enabled_protocols & RC_BIT_SONY12)) {
- data->state = STATE_INACTIVE;
- return 0;
- }
+ if (!(dev->enabled_protocols & RC_BIT_SONY12))
+ goto finish_state_machine;
+
device = bitrev8((data->bits << 3) & 0xF8);
subdevice = 0;
function = bitrev8((data->bits >> 4) & 0xFE);
protocol = RC_TYPE_SONY12;
break;
case 15:
- if (!(dev->enabled_protocols & RC_BIT_SONY15)) {
- data->state = STATE_INACTIVE;
- return 0;
- }
+ if (!(dev->enabled_protocols & RC_BIT_SONY15))
+ goto finish_state_machine;
+
device = bitrev8((data->bits >> 0) & 0xFF);
subdevice = 0;
function = bitrev8((data->bits >> 7) & 0xFE);
protocol = RC_TYPE_SONY15;
break;
case 20:
- if (!(dev->enabled_protocols & RC_BIT_SONY20)) {
- data->state = STATE_INACTIVE;
- return 0;
- }
+ if (!(dev->enabled_protocols & RC_BIT_SONY20))
+ goto finish_state_machine;
+
device = bitrev8((data->bits >> 5) & 0xF8);
subdevice = bitrev8((data->bits >> 0) & 0xFF);
function = bitrev8((data->bits >> 12) & 0xFE);
scancode = device << 16 | subdevice << 8 | function;
IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
rc_keydown(dev, protocol, scancode, 0);
- data->state = STATE_INACTIVE;
- return 0;
+ goto finish_state_machine;
}
out:
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
+
+finish_state_machine:
+ data->state = STATE_INACTIVE;
+ return 0;
}
static struct ir_raw_handler sony_handler = {
if (rdev) {
mutex_lock(&rdev->lock);
- if (!--rdev->users && rdev->close != NULL)
+ if (!--rdev->users && rdev->close != NULL)
rdev->close(rdev);
mutex_unlock(&rdev->lock);
}
/* Util fn to send rr3 cmds */
-static u8 redrat3_send_cmd(int cmd, struct redrat3_dev *rr3)
+static int redrat3_send_cmd(int cmd, struct redrat3_dev *rr3)
{
struct usb_device *udev;
u8 *data;
int err = 0;
u8 i, tmpval, *valptr = NULL;
- qt1010_i2c_oper_t i2c_data[] = {
+ static const qt1010_i2c_oper_t i2c_data[] = {
{ QT1010_WR, 0x01, 0x80 },
{ QT1010_WR, 0x0d, 0x84 },
{ QT1010_WR, 0x0e, 0xb7 },
valptr = &priv->reg1f_init_val;
else
valptr = &tmpval;
+
+ BUG_ON(i >= ARRAY_SIZE(i2c_data) - 1);
+
err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
i2c_data[i].reg,
i2c_data[i].val, valptr);
i++;
break;
}
- if (err) return err;
+ if (err)
+ return err;
}
for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
rc = r820t_write_reg_mask(priv, 0x10, 0x00, 0x04);
if (rc < 0)
return rc;
- }
- return 0;
+ }
+ return 0;
}
static int r820t_set_tv_standard(struct r820t_priv *priv,
* Still need tests for XC3028L (firmware 3.2 or upper)
* So, for now, let's just comment the per-firmware
* version of this change. Reports with xc3028l working
- * with and without the lines bellow are welcome
+ * with and without the lines below are welcome
*/
if (priv->firm_version < 0x0302) {
&as102_dev->bus_adap,
as102_dev->elna_cfg);
if (!as102_dev->dvb_fe) {
+ ret = -ENODEV;
dev_err(dev, "%s: as102_attach() failed: %d",
__func__, ret);
goto efereg;
}
cx231xx_enable656(dev);
- /* stop mpeg capture */
- cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE,
- 3, 0, 1, 3, 4);
+
+ /* stop mpeg capture */
+ cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 1, 3, 4);
cx231xx_codec_settings(dev);
msleep(60);
{
struct cx231xx *dev = container_of(cxhdl, struct cx231xx, mpeg_ctrl_handler);
int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
/* fix videodecoder resolution */
- fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
- fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
- v4l2_subdev_call(dev->sd_cx25840, video, s_mbus_fmt, &fmt);
+ format.format.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+ format.format.height = cxhdl->height;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ v4l2_subdev_call(dev->sd_cx25840, pad, set_fmt, NULL, &format);
return 0;
}
/*pll_freq_word = 0x3463497;*/
vid_blk_write_word(dev, DIF_PLL_FREQ_WORD, pll_freq_word);
- if (spectral_invert) {
- if_freq -= 400000;
- /* Enable Spectral Invert*/
- vid_blk_read_word(dev, DIF_MISC_CTRL,
- &dif_misc_ctrl_value);
- dif_misc_ctrl_value = dif_misc_ctrl_value | 0x00200000;
- vid_blk_write_word(dev, DIF_MISC_CTRL,
- dif_misc_ctrl_value);
- } else {
- if_freq += 400000;
- /* Disable Spectral Invert*/
- vid_blk_read_word(dev, DIF_MISC_CTRL,
- &dif_misc_ctrl_value);
- dif_misc_ctrl_value = dif_misc_ctrl_value & 0xFFDFFFFF;
- vid_blk_write_word(dev, DIF_MISC_CTRL,
- dif_misc_ctrl_value);
- }
+ if (spectral_invert) {
+ if_freq -= 400000;
+ /* Enable Spectral Invert*/
+ vid_blk_read_word(dev, DIF_MISC_CTRL,
+ &dif_misc_ctrl_value);
+ dif_misc_ctrl_value = dif_misc_ctrl_value | 0x00200000;
+ vid_blk_write_word(dev, DIF_MISC_CTRL,
+ dif_misc_ctrl_value);
+ } else {
+ if_freq += 400000;
+ /* Disable Spectral Invert*/
+ vid_blk_read_word(dev, DIF_MISC_CTRL,
+ &dif_misc_ctrl_value);
+ dif_misc_ctrl_value = dif_misc_ctrl_value & 0xFFDFFFFF;
+ vid_blk_write_word(dev, DIF_MISC_CTRL,
+ dif_misc_ctrl_value);
+ }
- if_freq = (if_freq/100000)*100000;
+ if_freq = (if_freq / 100000) * 100000;
- if (if_freq < 3000000)
- if_freq = 3000000;
+ if (if_freq < 3000000)
+ if_freq = 3000000;
- if (if_freq > 16000000)
- if_freq = 16000000;
+ if (if_freq > 16000000)
+ if_freq = 16000000;
}
dev_dbg(dev->dev, "Enter IF=%zu\n", ARRAY_SIZE(Dif_set_array));
cx231xx_coredbg("Enter cx231xx_demod_reset()\n");
- value[1] = (u8) 0x3;
- status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
- PWR_CTL_EN, value, 4);
- msleep(10);
-
- value[1] = (u8) 0x0;
- status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
- PWR_CTL_EN, value, 4);
- msleep(10);
-
- value[1] = (u8) 0x3;
- status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
- PWR_CTL_EN, value, 4);
- msleep(10);
-
-
+ value[1] = (u8) 0x3;
+ status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+ PWR_CTL_EN, value, 4);
+ msleep(10);
+
+ value[1] = (u8) 0x0;
+ status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+ PWR_CTL_EN, value, 4);
+ msleep(10);
+
+ value[1] = (u8) 0x3;
+ status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+ PWR_CTL_EN, value, 4);
+ msleep(10);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
value, 4);
struct cx231xx *dev = fh->dev;
int rc;
struct cx231xx_fmt *fmt;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
rc = check_dev(dev);
if (rc < 0)
dev->height = f->fmt.pix.height;
dev->format = fmt;
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
- call_all(dev, video, s_mbus_fmt, &mbus_fmt);
- v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+ v4l2_fill_mbus_format(&format.format, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ call_all(dev, pad, set_fmt, NULL, &format);
+ v4l2_fill_pix_format(&f->fmt.pix, &format.format);
return rc;
}
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
int rc;
rc = check_dev(dev);
/* We need to reset basic properties in the decoder related to
resolution (since a standard change effects things like the number
of lines in VACT, etc) */
- memset(&mbus_fmt, 0, sizeof(mbus_fmt));
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
- mbus_fmt.width = dev->width;
- mbus_fmt.height = dev->height;
- call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ format.format.width = dev->width;
+ format.format.height = dev->height;
+ call_all(dev, pad, set_fmt, NULL, &format);
/* do mode control overrides */
cx231xx_do_mode_ctrl_overrides(dev);
return ret;
if (temp != state->strong) {
deb_info("adjust for strong signal %d\n", temp);
- state->strong = temp;
+ state->strong = temp;
}
return 0;
}
struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dib0700_adapter_state *state = adap->priv;
- u16 offset;
- u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
- switch (band) {
- case BAND_VHF:
- state->dib7000p_ops.set_gpio(fe, 0, 0, 1);
- offset = 850;
- break;
- case BAND_UHF:
- default:
- state->dib7000p_ops.set_gpio(fe, 0, 0, 0);
- offset = 250;
- break;
- }
- deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
- state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
- return state->set_param_save(fe);
+ u16 offset;
+ u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
+ switch (band) {
+ case BAND_VHF:
+ state->dib7000p_ops.set_gpio(fe, 0, 0, 1);
+ offset = 850;
+ break;
+ case BAND_UHF:
+ default:
+ state->dib7000p_ops.set_gpio(fe, 0, 0, 0);
+ offset = 250;
+ break;
+ }
+ deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ return state->set_param_save(fe);
}
static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
ibuf, msg[j].len + 2,
DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf + 2, msg[j].len);
- mdelay(10);
+ mdelay(10);
} else if (((msg[j].buf[0] == 0xb0) &&
(msg[j].addr == 0x68)) ||
((msg[j].buf[0] == 0xf7) &&
/* remote control stuff (does not work with my box) */
static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
+/* remove the following return to enabled remote querying */
+#if 0
u8 *key;
int i;
-/* remove the following return to enabled remote querying */
- return 0;
-
key = kmalloc(10, GFP_KERNEL);
if (!key)
return -ENOMEM;
break;
}
kfree(key);
+#endif
+
return 0;
}
.addr = client->addr,
.platform_data = &camlink,
};
- struct v4l2_mbus_framefmt fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
/*
* FIXME: sensor supports resolutions up to 1600x1200, but
break;
}
- fmt.code = MEDIA_BUS_FMT_YUYV8_2X8;
- fmt.width = 640;
- fmt.height = 480;
- v4l2_subdev_call(subdev, video, s_mbus_fmt, &fmt);
+ format.format.code = MEDIA_BUS_FMT_YUYV8_2X8;
+ format.format.width = 640;
+ format.format.height = 480;
+ v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format);
/* NOTE: for UXGA=1600x1200 switch to 12MHz */
dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ;
*/
static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
{
- u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ u32 *bytesused;
struct go7007_buffer *vb_tmp = NULL;
if (vb == NULL) {
go->next_seq++;
return vb;
}
+ bytesused = &vb->vb.v4l2_planes[0].bytesused;
vb->vb.v4l2_buf.sequence = go->next_seq++;
if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
},
};
+#if 0
static const struct go7007_usb_board board_lifeview_lr192 = {
.flags = GO7007_USB_EZUSB,
.main_info = {
},
},
};
+#endif
static const struct go7007_usb_board board_endura = {
.flags = 0,
case GO7007_BOARDID_LIFEVIEW_LR192:
dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n");
return -ENODEV;
+#if 0
name = "Lifeview TV Walker Ultra";
board = &board_lifeview_lr192;
+#endif
break;
case GO7007_BOARDID_SENSORAY_2250:
dev_info(&intf->dev, "Sensoray 2250 found\n");
go->encoder_v_offset = go->board_info->sensor_v_offset;
if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
- struct v4l2_mbus_framefmt mbus_fmt;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
- mbus_fmt.width = fmt ? fmt->fmt.pix.width : width;
- mbus_fmt.height = height;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
+ format.format.width = fmt ? fmt->fmt.pix.width : width;
+ format.format.height = height;
go->encoder_h_halve = 0;
go->encoder_v_halve = 0;
go->encoder_subsample = 0;
- call_all(&go->v4l2_dev, video, s_mbus_fmt, &mbus_fmt);
+ call_all(&go->v4l2_dev, pad, set_fmt, NULL, &format);
} else {
if (width <= sensor_width / 4) {
go->encoder_h_halve = 1;
return 0;
}
-static int s2250_s_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt)
+static int s2250_set_fmt(struct v4l2_subdev *sd,
+ struct v4l2_subdev_pad_config *cfg,
+ struct v4l2_subdev_format *format)
{
+ struct v4l2_mbus_framefmt *fmt = &format->format;
struct s2250 *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
+ if (format->pad)
+ return -EINVAL;
+
+ if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+ return 0;
+
if (fmt->height < 640) {
write_reg_fp(client, 0x12b, state->reg12b_val | 0x400);
write_reg_fp(client, 0x140, 0x060);
static const struct v4l2_subdev_video_ops s2250_video_ops = {
.s_std = s2250_s_std,
.s_routing = s2250_s_video_routing,
- .s_mbus_fmt = s2250_s_mbus_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops s2250_pad_ops = {
+ .set_fmt = s2250_set_fmt,
};
static const struct v4l2_subdev_ops s2250_ops = {
.core = &s2250_core_ops,
.audio = &s2250_audio_ops,
.video = &s2250_video_ops,
+ .pad = &s2250_pad_ops,
};
/* --------------------------------------------------------------------------*/
}
data = (u8 *) urb->transfer_buffer
+ urb->iso_frame_desc[i].offset;
- gspca_frame_add(gspca_dev, INTER_PACKET,
- data, SD_PKT_SZ);
+ gspca_frame_add(gspca_dev, INTER_PACKET,
+ data, SD_PKT_SZ);
}
/* resubmit the URBs */
if (expo > 0x03ff)
expo = 0x03ff;
- if (expo < 0x0001)
+ if (expo < 0x0001)
expo = 0x0001;
gainOm[3] = expo >> 2;
i2c_w8(gspca_dev, gainOm);
gspca_dev->usb_err = ret;
goto out;
}
- reg_r(gspca_dev, 0x0630);
+ reg_r(gspca_dev, 0x0630);
rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
reg_r(gspca_dev, 0x0650);
snd_val(gspca_dev, 0x000020, 0xffffffff);
cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
sd->sof_len = 2;
break;
- /* case VIDEOSIZE_352x240: */
+#if 0
+ case VIDEOSIZE_352x240:
cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
cit_write_reg(gspca_dev, 0x001e, 0x0105); /* 320x240, 352x240 */
cit_write_reg(gspca_dev, 0x0070, 0x0119); /* All except 176x144 */
sd->sof_len = 2;
break;
+#endif
case 352: /* 352x288 */
cit_write_reg(gspca_dev, 0x002c, 0x0103); /* All except 320x240 */
cit_write_reg(gspca_dev, 0x0000, 0x0104); /* Same */
cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */
clock_div = 8;
break;
- /* case VIDEOSIZE_352x240: */
+#if 0
+ case VIDEOSIZE_352x240:
/* This mode doesn't work as Windows programs it; changed to work */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */
cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */
cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
clock_div = 10;
break;
+#endif
case 352: /* 352x288 */
cit_model2_Packet1(gspca_dev, 0x0014, 0x0003);
cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
case 320: /* 320x240 */
cit_model2_Packet1(gspca_dev, 0x0026, 0x0044);
break;
- /* case VIDEOSIZE_352x240: */
+#if 0
+ case VIDEOSIZE_352x240:
cit_model2_Packet1(gspca_dev, 0x0026, 0x0046);
break;
+#endif
case 352: /* 352x288 */
cit_model2_Packet1(gspca_dev, 0x0026, 0x0048);
break;
reg07 = 0;
good = 0;
- for (;;) {
+ while (1) {
msleep(100);
/* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
mutex_lock(&gspca_dev->usb_lock);
#ifdef CONFIG_PM
if (gspca_dev->frozen)
- goto err;
+ break;
#endif
if (!gspca_dev->present || !gspca_dev->streaming)
- goto err;
+ break;
/* Bit 0 of register 11 indicates FIFO overflow */
gspca_dev->usb_err = 0;
reg11 = reg_r(gspca_dev, 0x0011);
if (gspca_dev->usb_err)
- goto err;
+ break;
change = reg11 & 0x01;
if (change) { /* overflow */
gspca_dev->usb_err = 0;
reg_w(gspca_dev, reg07, 0x0007);
if (gspca_dev->usb_err)
- goto err;
+ break;
}
mutex_unlock(&gspca_dev->usb_lock);
}
- return;
-err:
+
+ /* Something went wrong. Unlock and return */
mutex_unlock(&gspca_dev->usb_lock);
}
if (ctrl->val <= jpeg_qual[i])
break;
}
- if (i > 0 && i == qual && ctrl->val < jpeg_qual[i])
+ if (i == ARRAY_SIZE(jpeg_qual) || (i > 0 && i == qual && ctrl->val < jpeg_qual[i]))
i--;
/* With high quality settings we need max bandwidth */
if (!sp) break;
sp->user = cp;
cp->stream = sp;
- } while (0); pvr2_context_exit(cp->mc_head);
+ } while (0);
+ pvr2_context_exit(cp->mc_head);
return code;
}
"Error registering with v4l core, giving up");
goto fail;
}
- mutex_lock(&pvr2_unit_mtx); do {
+ mutex_lock(&pvr2_unit_mtx);
+ do {
for (idx = 0; idx < PVR_NUM; idx++) {
if (unit_pointers[idx]) continue;
hdw->unit_number = idx;
unit_pointers[idx] = hdw;
break;
}
- } while (0); mutex_unlock(&pvr2_unit_mtx);
+ } while (0);
+ mutex_unlock(&pvr2_unit_mtx);
cnt1 = 0;
cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
pvr2_i2c_core_done(hdw);
v4l2_device_unregister(&hdw->v4l2_dev);
pvr2_hdw_remove_usb_stuff(hdw);
- mutex_lock(&pvr2_unit_mtx); do {
+ mutex_lock(&pvr2_unit_mtx);
+ do {
if ((hdw->unit_number >= 0) &&
(hdw->unit_number < PVR_NUM) &&
(unit_pointers[hdw->unit_number] == hdw)) {
unit_pointers[hdw->unit_number] = NULL;
}
- } while (0); mutex_unlock(&pvr2_unit_mtx);
+ } while (0);
+ mutex_unlock(&pvr2_unit_mtx);
kfree(hdw->controls);
kfree(hdw->mpeg_ctrl_info);
kfree(hdw);
}
if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
- struct v4l2_mbus_framefmt fmt;
- memset(&fmt, 0, sizeof(fmt));
- fmt.width = hdw->res_hor_val;
- fmt.height = hdw->res_ver_val;
- fmt.code = MEDIA_BUS_FMT_FIXED;
+ struct v4l2_subdev_format format = {
+ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+ };
+
+ format.format.width = hdw->res_hor_val;
+ format.format.height = hdw->res_ver_val;
+ format.format.code = MEDIA_BUS_FMT_FIXED;
pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
- fmt.width, fmt.height);
- v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
+ format.format.width, format.format.height);
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, pad, set_fmt,
+ NULL, &format);
}
if (hdw->srate_dirty || hdw->force_dirty) {
void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
{
int nr = pvr2_hdw_get_unit_number(hdw);
- LOCK_TAKE(hdw->big_lock); do {
+ LOCK_TAKE(hdw->big_lock);
+ do {
printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
pvr2_hdw_state_log_state(hdw);
printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
- } while (0); LOCK_GIVE(hdw->big_lock);
+ } while (0);
+ LOCK_GIVE(hdw->big_lock);
}
void *data)
{
unsigned long irq_flags;
- mutex_lock(&sp->mutex); do {
+ mutex_lock(&sp->mutex);
+ do {
spin_lock_irqsave(&sp->list_lock,irq_flags);
sp->callback_data = data;
sp->callback_func = func;
spin_unlock_irqrestore(&sp->list_lock,irq_flags);
- } while(0); mutex_unlock(&sp->mutex);
+ } while(0);
+ mutex_unlock(&sp->mutex);
}
void pvr2_stream_get_stats(struct pvr2_stream *sp,
{
int ret;
if (sp->buffer_target_count == cnt) return 0;
- mutex_lock(&sp->mutex); do {
+ mutex_lock(&sp->mutex);
+ do {
sp->buffer_target_count = cnt;
ret = pvr2_stream_achieve_buffer_count(sp);
- } while(0); mutex_unlock(&sp->mutex);
+ } while(0);
+ mutex_unlock(&sp->mutex);
return ret;
}
void pvr2_stream_kill(struct pvr2_stream *sp)
{
struct pvr2_buffer *bp;
- mutex_lock(&sp->mutex); do {
+ mutex_lock(&sp->mutex);
+ do {
pvr2_stream_internal_flush(sp);
while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
pvr2_buffer_set_idle(bp);
if (sp->buffer_total_count != sp->buffer_target_count) {
pvr2_stream_achieve_buffer_count(sp);
}
- } while(0); mutex_unlock(&sp->mutex);
+ } while(0);
+ mutex_unlock(&sp->mutex);
}
int pvr2_buffer_queue(struct pvr2_buffer *bp)
struct pvr2_stream *sp;
if (!bp) return -EINVAL;
sp = bp->stream;
- mutex_lock(&sp->mutex); do {
+ mutex_lock(&sp->mutex);
+ do {
pvr2_buffer_wipe(bp);
if (!sp->dev) {
ret = -EIO;
buffer_complete,
bp);
usb_submit_urb(bp->purb,GFP_KERNEL);
- } while(0); mutex_unlock(&sp->mutex);
+ } while(0);
+ mutex_unlock(&sp->mutex);
return ret;
}
struct pvr2_stream *sp;
if (!bp) return -EINVAL;
sp = bp->stream;
- mutex_lock(&sp->mutex); do {
+ mutex_lock(&sp->mutex);
+ do {
spin_lock_irqsave(&sp->list_lock,irq_flags);
if (bp->state != pvr2_buffer_state_idle) {
ret = -EPERM;
bp->stream->i_bcount,bp->stream->i_count);
}
spin_unlock_irqrestore(&sp->list_lock,irq_flags);
- } while(0); mutex_unlock(&sp->mutex);
+ } while(0);
+ mutex_unlock(&sp->mutex);
return ret;
}
unsigned int idx;
struct pvr2_buffer *bp;
- mutex_lock(&cp->mutex); do {
+ mutex_lock(&cp->mutex);
+ do {
if (cp->stream) {
pvr2_trace(PVR2_TRACE_START_STOP,
"/*---TRACE_READ---*/"
}
cp->stream = sp;
}
- } while (0); mutex_unlock(&cp->mutex);
+ } while (0);
+ mutex_unlock(&cp->mutex);
return 0;
}
int ret = 0;
if ((!fl) == (!(cp->enabled))) return ret;
- mutex_lock(&cp->mutex); do {
+ mutex_lock(&cp->mutex);
+ do {
if (fl) {
ret = pvr2_ioread_start(cp);
} else {
pvr2_ioread_stop(cp);
}
- } while (0); mutex_unlock(&cp->mutex);
+ } while (0);
+ mutex_unlock(&cp->mutex);
return ret;
}
// Search the stream for our synchronization key. This is made
// complicated by the fact that in order to be honest with
// ourselves here we must search across buffer boundaries...
- mutex_lock(&cp->mutex); while (1) {
+ mutex_lock(&cp->mutex);
+ while (1) {
// Ensure we have a buffer
if (!pvr2_ioread_get_buffer(cp)) break;
if (!cp->c_data_len) break;
}
continue; // (for clarity)
- } mutex_unlock(&cp->mutex);
+ }
+ mutex_unlock(&cp->mutex);
}
int pvr2_ioread_avail(struct pvr2_ioread *cp)
cp->stream_running = !0;
- mutex_lock(&cp->mutex); do {
+ mutex_lock(&cp->mutex);
+ do {
// Suck data out of the buffers and copy to the user
copied_cnt = 0;
}
}
- } while (0); mutex_unlock(&cp->mutex);
+ } while (0);
+ mutex_unlock(&cp->mutex);
if (!ret) {
if (copied_cnt) {
__func__, model);
return -ENOENT;
}
- if (version >= 0x01770000)
- dec->can_playback = 1;
+ if (version >= 0x01770000)
+ dec->can_playback = 1;
}
return 0;
}
};
static int usbtv_queue_setup(struct vb2_queue *vq,
- const struct v4l2_format *v4l_fmt, unsigned int *nbuffers,
+ const struct v4l2_format *fmt, unsigned int *nbuffers,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
struct usbtv *usbtv = vb2_get_drv_priv(vq);
+ unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
- if (*nbuffers < 2)
- *nbuffers = 2;
+ if (vq->num_buffers + *nbuffers < 2)
+ *nbuffers = 2 - vq->num_buffers;
*nplanes = 1;
- sizes[0] = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32);
+ if (fmt && fmt->fmt.pix.sizeimage < size)
+ return -EINVAL;
+ sizes[0] = fmt ? fmt->fmt.pix.sizeimage : size;
return 0;
}
if (usbtv->udev == NULL)
return -ENODEV;
+ usbtv->sequence = 0;
return usbtv_start(usbtv);
}
/* Submit all URBs */
for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
- err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb,
- GFP_KERNEL);
+ err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb,
+ GFP_KERNEL);
if (err_code) {
dev_err(&usbvision->dev->dev,
"%s: usb_submit_urb(%d) failed: error %d\n",
config VIDEOBUF2_DMA_SG
tristate
- #depends on HAS_DMA
+ depends on HAS_DMA
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
#define CVT_MIN_V_BPORCH 7 /* lines */
#define CVT_MIN_V_PORCH_RND 3 /* lines */
#define CVT_MIN_VSYNC_BP 550 /* min time of vsync + back porch (us) */
+#define CVT_HSYNC_PERCENT 8 /* nominal hsync as percentage of line */
/* Normal blanking for CVT uses GTF to calculate horizontal blanking */
#define CVT_CELL_GRAN 8 /* character cell granularity */
else
return false;
+ if (hfreq == 0)
+ return false;
+
/* Vertical */
if (reduced_blanking) {
v_fp = CVT_RB_V_FPORCH;
- v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 1999999) / 1000000;
+ v_bp = (CVT_RB_MIN_V_BLANK * hfreq) / 1000000 + 1;
v_bp -= vsync + v_fp;
if (v_bp < CVT_RB_MIN_V_BPORCH)
v_bp = CVT_RB_MIN_V_BPORCH;
} else {
v_fp = CVT_MIN_V_PORCH_RND;
- v_bp = (CVT_MIN_VSYNC_BP * hfreq + 1999999) / 1000000 - vsync;
+ v_bp = (CVT_MIN_VSYNC_BP * hfreq) / 1000000 + 1 - vsync;
if (v_bp < CVT_MIN_V_BPORCH)
v_bp = CVT_MIN_V_BPORCH;
}
image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
+ if (image_height < 0)
+ return false;
+
/* Aspect ratio based on vsync */
switch (vsync) {
case 4:
h_bp = h_blank / 2;
frame_width = image_width + h_blank;
- hsync = (frame_width * 8 + 50) / 100;
- hsync = hsync - hsync % CVT_CELL_GRAN;
+ hsync = frame_width * CVT_HSYNC_PERCENT / 100;
+ hsync = (hsync / CVT_CELL_GRAN) * CVT_CELL_GRAN;
h_fp = h_blank - hsync - h_bp;
}
else
return false;
+ if (hfreq == 0)
+ return false;
+
/* Vertical */
v_fp = GTF_V_FP;
- v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync;
+
+ v_bp = (GTF_MIN_VSYNC_BP * hfreq + 500000) / 1000000 - vsync;
image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
+ if (image_height < 0)
+ return false;
+
if (aspect.numerator == 0 || aspect.denominator == 0) {
aspect.numerator = 16;
aspect.denominator = 9;
(hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) /
(hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000);
- h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN);
+ h_blank = ((h_blank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN)) *
+ (2 * GTF_CELL_GRAN);
frame_width = image_width + h_blank;
pix_clk = (image_width + h_blank) * hfreq;
pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN;
hsync = (frame_width * 8 + 50) / 100;
- hsync = hsync - hsync % GTF_CELL_GRAN;
+ hsync = ((hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN) * GTF_CELL_GRAN;
h_fp = h_blank / 2 - hsync;
return ops->vidioc_enum_output(file, fh, p);
}
+static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
+{
+ const unsigned sz = sizeof(fmt->description);
+ const char *descr = NULL;
+ u32 flags = 0;
+
+ /*
+ * We depart from the normal coding style here since the descriptions
+ * should be aligned so it is easy to see which descriptions will be
+ * longer than 31 characters (the max length for a description).
+ * And frankly, this is easier to read anyway.
+ *
+ * Note that gcc will use O(log N) comparisons to find the right case.
+ */
+ switch (fmt->pixelformat) {
+ /* Max description length mask: descr = "0123456789012345678901234567890" */
+ case V4L2_PIX_FMT_RGB332: descr = "8-bit RGB 3-3-2"; break;
+ case V4L2_PIX_FMT_RGB444: descr = "16-bit A/XRGB 4-4-4-4"; break;
+ case V4L2_PIX_FMT_ARGB444: descr = "16-bit ARGB 4-4-4-4"; break;
+ case V4L2_PIX_FMT_XRGB444: descr = "16-bit XRGB 4-4-4-4"; break;
+ case V4L2_PIX_FMT_RGB555: descr = "16-bit A/XRGB 1-5-5-5"; break;
+ case V4L2_PIX_FMT_ARGB555: descr = "16-bit ARGB 1-5-5-5"; break;
+ case V4L2_PIX_FMT_XRGB555: descr = "16-bit XRGB 1-5-5-5"; break;
+ case V4L2_PIX_FMT_RGB565: descr = "16-bit RGB 5-6-5"; break;
+ case V4L2_PIX_FMT_RGB555X: descr = "16-bit A/XRGB 1-5-5-5 BE"; break;
+ case V4L2_PIX_FMT_ARGB555X: descr = "16-bit ARGB 1-5-5-5 BE"; break;
+ case V4L2_PIX_FMT_XRGB555X: descr = "16-bit XRGB 1-5-5-5 BE"; break;
+ case V4L2_PIX_FMT_RGB565X: descr = "16-bit RGB 5-6-5 BE"; break;
+ case V4L2_PIX_FMT_BGR666: descr = "18-bit BGRX 6-6-6-14"; break;
+ case V4L2_PIX_FMT_BGR24: descr = "24-bit BGR 8-8-8"; break;
+ case V4L2_PIX_FMT_RGB24: descr = "24-bit RGB 8-8-8"; break;
+ case V4L2_PIX_FMT_BGR32: descr = "32-bit BGRA/X 8-8-8-8"; break;
+ case V4L2_PIX_FMT_ABGR32: descr = "32-bit BGRA 8-8-8-8"; break;
+ case V4L2_PIX_FMT_XBGR32: descr = "32-bit BGRX 8-8-8-8"; break;
+ case V4L2_PIX_FMT_RGB32: descr = "32-bit A/XRGB 8-8-8-8"; break;
+ case V4L2_PIX_FMT_ARGB32: descr = "32-bit ARGB 8-8-8-8"; break;
+ case V4L2_PIX_FMT_XRGB32: descr = "32-bit XRGB 8-8-8-8"; break;
+ case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y10: descr = "10-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y12: descr = "12-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y16: descr = "16-bit Greyscale"; break;
+ case V4L2_PIX_FMT_Y10BPACK: descr = "10-bit Greyscale (Packed)"; break;
+ case V4L2_PIX_FMT_PAL8: descr = "8-bit Palette"; break;
+ case V4L2_PIX_FMT_UV8: descr = "8-bit Chrominance UV 4-4"; break;
+ case V4L2_PIX_FMT_YVU410: descr = "Planar YVU 4:1:0"; break;
+ case V4L2_PIX_FMT_YVU420: descr = "Planar YVU 4:2:0"; break;
+ case V4L2_PIX_FMT_YUYV: descr = "YUYV 4:2:2"; break;
+ case V4L2_PIX_FMT_YYUV: descr = "YYUV 4:2:2"; break;
+ case V4L2_PIX_FMT_YVYU: descr = "YVYU 4:2:2"; break;
+ case V4L2_PIX_FMT_UYVY: descr = "UYVY 4:2:2"; break;
+ case V4L2_PIX_FMT_VYUY: descr = "VYUY 4:2:2"; break;
+ case V4L2_PIX_FMT_YUV422P: descr = "Planar YVU 4:2:2"; break;
+ case V4L2_PIX_FMT_YUV411P: descr = "Planar YUV 4:1:1"; break;
+ case V4L2_PIX_FMT_Y41P: descr = "YUV 4:1:1 (Packed)"; break;
+ case V4L2_PIX_FMT_YUV444: descr = "16-bit A/XYUV 4-4-4-4"; break;
+ case V4L2_PIX_FMT_YUV555: descr = "16-bit A/XYUV 1-5-5-5"; break;
+ case V4L2_PIX_FMT_YUV565: descr = "16-bit YUV 5-6-5"; break;
+ case V4L2_PIX_FMT_YUV32: descr = "32-bit A/XYUV 8-8-8-8"; break;
+ case V4L2_PIX_FMT_YUV410: descr = "Planar YUV 4:1:0"; break;
+ case V4L2_PIX_FMT_YUV420: descr = "Planar YUV 4:2:0"; break;
+ case V4L2_PIX_FMT_HI240: descr = "8-bit Dithered RGB (BTTV)"; break;
+ case V4L2_PIX_FMT_HM12: descr = "YUV 4:2:0 (16x16 Macroblocks)"; break;
+ case V4L2_PIX_FMT_M420: descr = "YUV 4:2:0 (M420)"; break;
+ case V4L2_PIX_FMT_NV12: descr = "Y/CbCr 4:2:0"; break;
+ case V4L2_PIX_FMT_NV21: descr = "Y/CrCb 4:2:0"; break;
+ case V4L2_PIX_FMT_NV16: descr = "Y/CbCr 4:2:2"; break;
+ case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break;
+ case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break;
+ case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break;
+ case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break;
+ case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break;
+ case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break;
+ case V4L2_PIX_FMT_NV61M: descr = "Y/CrCb 4:2:2 (N-C)"; break;
+ case V4L2_PIX_FMT_NV12MT: descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break;
+ case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break;
+ case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break;
+ case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break;
+ case V4L2_PIX_FMT_SBGGR8: descr = "8-bit Bayer BGBG/GRGR"; break;
+ case V4L2_PIX_FMT_SGBRG8: descr = "8-bit Bayer GBGB/RGRG"; break;
+ case V4L2_PIX_FMT_SGRBG8: descr = "8-bit Bayer GRGR/BGBG"; break;
+ case V4L2_PIX_FMT_SRGGB8: descr = "8-bit Bayer RGRG/GBGB"; break;
+ case V4L2_PIX_FMT_SBGGR10: descr = "10-bit Bayer BGBG/GRGR"; break;
+ case V4L2_PIX_FMT_SGBRG10: descr = "10-bit Bayer GBGB/RGRG"; break;
+ case V4L2_PIX_FMT_SGRBG10: descr = "10-bit Bayer GRGR/BGBG"; break;
+ case V4L2_PIX_FMT_SRGGB10: descr = "10-bit Bayer RGRG/GBGB"; break;
+ case V4L2_PIX_FMT_SBGGR12: descr = "12-bit Bayer BGBG/GRGR"; break;
+ case V4L2_PIX_FMT_SGBRG12: descr = "12-bit Bayer GBGB/RGRG"; break;
+ case V4L2_PIX_FMT_SGRBG12: descr = "12-bit Bayer GRGR/BGBG"; break;
+ case V4L2_PIX_FMT_SRGGB12: descr = "12-bit Bayer RGRG/GBGB"; break;
+ case V4L2_PIX_FMT_SBGGR10P: descr = "10-bit Bayer BGBG/GRGR Packed"; break;
+ case V4L2_PIX_FMT_SGBRG10P: descr = "10-bit Bayer GBGB/RGRG Packed"; break;
+ case V4L2_PIX_FMT_SGRBG10P: descr = "10-bit Bayer GRGR/BGBG Packed"; break;
+ case V4L2_PIX_FMT_SRGGB10P: descr = "10-bit Bayer RGRG/GBGB Packed"; break;
+ case V4L2_PIX_FMT_SBGGR10ALAW8: descr = "8-bit Bayer BGBG/GRGR (A-law)"; break;
+ case V4L2_PIX_FMT_SGBRG10ALAW8: descr = "8-bit Bayer GBGB/RGRG (A-law)"; break;
+ case V4L2_PIX_FMT_SGRBG10ALAW8: descr = "8-bit Bayer GRGR/BGBG (A-law)"; break;
+ case V4L2_PIX_FMT_SRGGB10ALAW8: descr = "8-bit Bayer RGRG/GBGB (A-law)"; break;
+ case V4L2_PIX_FMT_SBGGR10DPCM8: descr = "8-bit Bayer BGBG/GRGR (DPCM)"; break;
+ case V4L2_PIX_FMT_SGBRG10DPCM8: descr = "8-bit Bayer GBGB/RGRG (DPCM)"; break;
+ case V4L2_PIX_FMT_SGRBG10DPCM8: descr = "8-bit Bayer GRGR/BGBG (DPCM)"; break;
+ case V4L2_PIX_FMT_SRGGB10DPCM8: descr = "8-bit Bayer RGRG/GBGB (DPCM)"; break;
+ case V4L2_PIX_FMT_SBGGR16: descr = "16-bit Bayer BGBG/GRGR (Exp.)"; break;
+ case V4L2_PIX_FMT_SN9C20X_I420: descr = "GSPCA SN9C20X I420"; break;
+ case V4L2_PIX_FMT_SPCA501: descr = "GSPCA SPCA501"; break;
+ case V4L2_PIX_FMT_SPCA505: descr = "GSPCA SPCA505"; break;
+ case V4L2_PIX_FMT_SPCA508: descr = "GSPCA SPCA508"; break;
+ case V4L2_PIX_FMT_STV0680: descr = "GSPCA STV0680"; break;
+ case V4L2_PIX_FMT_TM6000: descr = "A/V + VBI Mux Packet"; break;
+ case V4L2_PIX_FMT_CIT_YYVYUY: descr = "GSPCA CIT YYVYUY"; break;
+ case V4L2_PIX_FMT_KONICA420: descr = "GSPCA KONICA420"; break;
+ case V4L2_SDR_FMT_CU8: descr = "Complex U8 (Emulated)"; break;
+ case V4L2_SDR_FMT_CU16LE: descr = "Complex U16LE (Emulated)"; break;
+ case V4L2_SDR_FMT_CS8: descr = "Complex S8"; break;
+ case V4L2_SDR_FMT_CS14LE: descr = "Complex S14LE"; break;
+ case V4L2_SDR_FMT_RU12LE: descr = "Real U12LE"; break;
+
+ default:
+ /* Compressed formats */
+ flags = V4L2_FMT_FLAG_COMPRESSED;
+ switch (fmt->pixelformat) {
+ /* Max description length mask: descr = "0123456789012345678901234567890" */
+ case V4L2_PIX_FMT_MJPEG: descr = "Motion-JPEG"; break;
+ case V4L2_PIX_FMT_JPEG: descr = "JFIF JPEG"; break;
+ case V4L2_PIX_FMT_DV: descr = "1394"; break;
+ case V4L2_PIX_FMT_MPEG: descr = "MPEG-1/2/4"; break;
+ case V4L2_PIX_FMT_H264: descr = "H.264"; break;
+ case V4L2_PIX_FMT_H264_NO_SC: descr = "H.264 (No Start Codes)"; break;
+ case V4L2_PIX_FMT_H264_MVC: descr = "H.264 MVC"; break;
+ case V4L2_PIX_FMT_H263: descr = "H.263"; break;
+ case V4L2_PIX_FMT_MPEG1: descr = "MPEG-1 ES"; break;
+ case V4L2_PIX_FMT_MPEG2: descr = "MPEG-2 ES"; break;
+ case V4L2_PIX_FMT_MPEG4: descr = "MPEG-4 part 2 ES"; break;
+ case V4L2_PIX_FMT_XVID: descr = "Xvid"; break;
+ case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break;
+ case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break;
+ case V4L2_PIX_FMT_VP8: descr = "VP8"; break;
+ case V4L2_PIX_FMT_CPIA1: descr = "GSPCA CPiA YUV"; break;
+ case V4L2_PIX_FMT_WNVA: descr = "WNVA"; break;
+ case V4L2_PIX_FMT_SN9C10X: descr = "GSPCA SN9C10X"; break;
+ case V4L2_PIX_FMT_PWC1: descr = "Raw Philips Webcam Type (Old)"; break;
+ case V4L2_PIX_FMT_PWC2: descr = "Raw Philips Webcam Type (New)"; break;
+ case V4L2_PIX_FMT_ET61X251: descr = "GSPCA ET61X251"; break;
+ case V4L2_PIX_FMT_SPCA561: descr = "GSPCA SPCA561"; break;
+ case V4L2_PIX_FMT_PAC207: descr = "GSPCA PAC207"; break;
+ case V4L2_PIX_FMT_MR97310A: descr = "GSPCA MR97310A"; break;
+ case V4L2_PIX_FMT_JL2005BCD: descr = "GSPCA JL2005BCD"; break;
+ case V4L2_PIX_FMT_SN9C2028: descr = "GSPCA SN9C2028"; break;
+ case V4L2_PIX_FMT_SQ905C: descr = "GSPCA SQ905C"; break;
+ case V4L2_PIX_FMT_PJPG: descr = "GSPCA PJPG"; break;
+ case V4L2_PIX_FMT_OV511: descr = "GSPCA OV511"; break;
+ case V4L2_PIX_FMT_OV518: descr = "GSPCA OV518"; break;
+ case V4L2_PIX_FMT_JPGL: descr = "JPEG Lite"; break;
+ case V4L2_PIX_FMT_SE401: descr = "GSPCA SE401"; break;
+ case V4L2_PIX_FMT_S5C_UYVY_JPG: descr = "S5C73MX interleaved UYVY/JPEG"; break;
+ default:
+ WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat);
+ if (fmt->description[0])
+ return;
+ flags = 0;
+ snprintf(fmt->description, sz, "%c%c%c%c%s",
+ (char)(fmt->pixelformat & 0x7f),
+ (char)((fmt->pixelformat >> 8) & 0x7f),
+ (char)((fmt->pixelformat >> 16) & 0x7f),
+ (char)((fmt->pixelformat >> 24) & 0x7f),
+ (fmt->pixelformat & (1 << 31)) ? "-BE" : "");
+ break;
+ }
+ }
+
+ if (descr)
+ WARN_ON(strlcpy(fmt->description, descr, sz) >= sz);
+ fmt->flags = flags;
+}
+
static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret = -EINVAL;
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap))
break;
- return ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
+ ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
+ break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane))
break;
- return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
+ ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
+ break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay))
break;
- return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
+ ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
+ break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out))
break;
- return ops->vidioc_enum_fmt_vid_out(file, fh, arg);
+ ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg);
+ break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane))
break;
- return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
+ ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
+ break;
case V4L2_BUF_TYPE_SDR_CAPTURE:
if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap))
break;
- return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
+ ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
+ break;
}
- return -EINVAL;
+ if (ret == 0)
+ v4l_fill_fmtdesc(p);
+ return ret;
}
static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
* V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag.
* The caller should hold a reference to @node.
*
+ * NOTE: This function does not parse properties the size of which is
+ * variable without a low fixed limit. Please use
+ * v4l2_of_alloc_parse_endpoint() in new drivers instead.
+ *
* Return: 0.
*/
int v4l2_of_parse_endpoint(const struct device_node *node,
int rval;
of_graph_parse_endpoint(node, &endpoint->base);
- endpoint->bus_type = 0;
- memset(&endpoint->bus, 0, sizeof(endpoint->bus));
+ /* Zero fields from bus_type to until the end */
+ memset(&endpoint->bus_type, 0, sizeof(*endpoint) -
+ offsetof(typeof(*endpoint), bus_type));
rval = v4l2_of_parse_csi_bus(node, endpoint);
if (rval)
}
EXPORT_SYMBOL(v4l2_of_parse_endpoint);
+/*
+ * v4l2_of_free_endpoint() - free the endpoint acquired by
+ * v4l2_of_alloc_parse_endpoint()
+ * @endpoint - the endpoint the resources of which are to be released
+ *
+ * It is safe to call this function with NULL argument or on an
+ * endpoint the parsing of which failed.
+ */
+void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint)
+{
+ if (IS_ERR_OR_NULL(endpoint))
+ return;
+
+ kfree(endpoint->link_frequencies);
+ kfree(endpoint);
+}
+EXPORT_SYMBOL(v4l2_of_free_endpoint);
+
+/**
+ * v4l2_of_alloc_parse_endpoint() - parse all endpoint node properties
+ * @node: pointer to endpoint device_node
+ *
+ * All properties are optional. If none are found, we don't set any flags.
+ * This means the port has a static configuration and no properties have
+ * to be specified explicitly.
+ * If any properties that identify the bus as parallel are found and
+ * slave-mode isn't set, we set V4L2_MBUS_MASTER. Similarly, if we recognise
+ * the bus as serial CSI-2 and clock-noncontinuous isn't set, we set the
+ * V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag.
+ * The caller should hold a reference to @node.
+ *
+ * v4l2_of_alloc_parse_endpoint() has two important differences to
+ * v4l2_of_parse_endpoint():
+ *
+ * 1. It also parses variable size data and
+ *
+ * 2. The memory it has allocated to store the variable size data must
+ * be freed using v4l2_of_free_endpoint() when no longer needed.
+ *
+ * Return: Pointer to v4l2_of_endpoint if successful, on error a
+ * negative error code.
+ */
+struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint(
+ const struct device_node *node)
+{
+ struct v4l2_of_endpoint *endpoint;
+ int len;
+ int rval;
+
+ endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL);
+ if (!endpoint)
+ return ERR_PTR(-ENOMEM);
+
+ rval = v4l2_of_parse_endpoint(node, endpoint);
+ if (rval < 0)
+ goto out_err;
+
+ if (of_get_property(node, "link-frequencies", &len)) {
+ endpoint->link_frequencies = kmalloc(len, GFP_KERNEL);
+ if (!endpoint->link_frequencies) {
+ rval = -ENOMEM;
+ goto out_err;
+ }
+
+ endpoint->nr_of_link_frequencies =
+ len / sizeof(*endpoint->link_frequencies);
+
+ rval = of_property_read_u64_array(
+ node, "link-frequencies", endpoint->link_frequencies,
+ endpoint->nr_of_link_frequencies);
+ if (rval < 0)
+ goto out_err;
+ }
+
+ return endpoint;
+
+out_err:
+ v4l2_of_free_endpoint(endpoint);
+ return ERR_PTR(rval);
+}
+EXPORT_SYMBOL(v4l2_of_alloc_parse_endpoint);
+
/**
* v4l2_of_parse_link() - parse a link between two endpoints
* @node: pointer to the endpoint at the local end of the link
ret = __qbuf_mmap(vb, b);
break;
case V4L2_MEMORY_USERPTR:
- down_read(¤t->mm->mmap_sem);
ret = __qbuf_userptr(vb, b);
- up_read(¤t->mm->mmap_sem);
break;
case V4L2_MEMORY_DMABUF:
ret = __qbuf_dmabuf(vb, b);
sg_free_table(sgt);
kfree(sgt);
}
+ down_read(¤t->mm->mmap_sem);
vb2_put_vma(buf->vma);
+ up_read(¤t->mm->mmap_sem);
kfree(buf);
}
goto fail_buf;
}
+ down_read(¤t->mm->mmap_sem);
/* current->mm->mmap_sem is taken by videobuf2 core */
vma = find_vma(current->mm, vaddr);
if (!vma) {
if (ret) {
unsigned long pfn;
if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
+ up_read(¤t->mm->mmap_sem);
buf->dma_addr = vb2_dc_pfn_to_dma(buf->dev, pfn);
buf->size = size;
kfree(pages);
pr_err("failed to get user pages\n");
goto fail_vma;
}
+ up_read(¤t->mm->mmap_sem);
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt) {
while (n_pages)
put_page(pages[--n_pages]);
+ down_read(¤t->mm->mmap_sem);
fail_vma:
vb2_put_vma(buf->vma);
fail_pages:
+ up_read(¤t->mm->mmap_sem);
kfree(pages); /* kfree is NULL-proof */
fail_buf:
if (!buf->pages)
goto userptr_fail_alloc_pages;
+ down_read(¤t->mm->mmap_sem);
vma = find_vma(current->mm, vaddr);
if (!vma) {
dprintk(1, "no vma for address %lu\n", vaddr);
1, /* force */
buf->pages,
NULL);
+ up_read(¤t->mm->mmap_sem);
if (num_pages_from_user != buf->num_pages)
goto userptr_fail_get_user_pages;
if (!vma_is_io(buf->vma))
while (--num_pages_from_user >= 0)
put_page(buf->pages[num_pages_from_user]);
+ down_read(¤t->mm->mmap_sem);
vb2_put_vma(buf->vma);
userptr_fail_find_vma:
+ up_read(¤t->mm->mmap_sem);
kfree(buf->pages);
userptr_fail_alloc_pages:
kfree(buf);
put_page(buf->pages[i]);
}
kfree(buf->pages);
+ down_read(¤t->mm->mmap_sem);
vb2_put_vma(buf->vma);
+ up_read(¤t->mm->mmap_sem);
kfree(buf);
}
offset = vaddr & ~PAGE_MASK;
buf->size = size;
-
+ down_read(¤t->mm->mmap_sem);
vma = find_vma(current->mm, vaddr);
if (vma && (vma->vm_flags & VM_PFNMAP) && (vma->vm_pgoff)) {
if (vb2_get_contig_userptr(vaddr, size, &vma, &physp))
if (!buf->vaddr)
goto fail_get_user_pages;
}
+ up_read(¤t->mm->mmap_sem);
buf->vaddr += offset;
return buf;
kfree(buf->pages);
fail_pages_array_alloc:
+ up_read(¤t->mm->mmap_sem);
kfree(buf);
return NULL;
unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK;
unsigned int i;
+ down_read(¤t->mm->mmap_sem);
if (buf->pages) {
if (vaddr)
vm_unmap_ram((void *)vaddr, buf->n_pages);
vb2_put_vma(buf->vma);
iounmap((__force void __iomem *)buf->vaddr);
}
+ up_read(¤t->mm->mmap_sem);
kfree(buf);
}
source "drivers/staging/media/davinci_vpfe/Kconfig"
-source "drivers/staging/media/dt3155v4l/Kconfig"
-
source "drivers/staging/media/mn88472/Kconfig"
source "drivers/staging/media/mn88473/Kconfig"
obj-$(CONFIG_I2C_BCM2048) += bcm2048/
obj-$(CONFIG_DVB_CXD2099) += cxd2099/
obj-$(CONFIG_LIRC_STAGING) += lirc/
-obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
obj-$(CONFIG_DVB_MN88472) += mn88472/
const struct i2c_device_id *id)
{
struct bcm2048_device *bdev;
- int err, skip_release = 0;
+ int err;
bdev = kzalloc(sizeof(*bdev), GFP_KERNEL);
if (!bdev) {
bcm2048_sysfs_unregister_properties(bdev, ARRAY_SIZE(attrs));
free_registration:
video_unregister_device(&bdev->videodev);
- skip_release = 1;
free_irq:
if (client->irq)
free_irq(client->irq, bdev);
+++ /dev/null
-config VIDEO_DT3155
- tristate "DT3155 frame grabber, Video4Linux interface"
- depends on PCI && VIDEO_DEV && VIDEO_V4L2
- depends on HAS_DMA
- select VIDEOBUF2_DMA_CONTIG
- default n
- ---help---
- Enables dt3155 device driver for the DataTranslation DT3155 frame grabber.
- Say Y here if you have this hardware.
- In doubt, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called dt3155v4l.
-
-config DT3155_CCIR
- bool "Selects CCIR/50Hz vertical refresh"
- depends on VIDEO_DT3155
- default y
- ---help---
- Select it for CCIR/50Hz (European region),
- or leave it unselected for RS-170/60Hz (North America).
-
-config DT3155_STREAMING
- bool "Selects streaming capture method"
- depends on VIDEO_DT3155
- default y
- ---help---
- Select it if you want to use streaming of memory mapped buffers
- or leave it unselected if you want to use read method (one copy more).
+++ /dev/null
-obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l.o
+++ /dev/null
-/***************************************************************************
- * Copyright (C) 2006-2010 by Marin Mitov *
- * mitov@issp.bas.bg *
- * *
- * 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 *
- * (at your option) 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. *
- ***************************************************************************/
-
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "dt3155v4l.h"
-
-#define DT3155_DEVICE_ID 0x1223
-
-/* DT3155_CHUNK_SIZE is 4M (2^22) 8 full size buffers */
-#define DT3155_CHUNK_SIZE (1U << 22)
-
-#define DT3155_COH_FLAGS (GFP_KERNEL | GFP_DMA32 | __GFP_COLD | __GFP_NOWARN)
-
-#define DT3155_BUF_SIZE (768 * 576)
-
-#ifdef CONFIG_DT3155_STREAMING
-#define DT3155_CAPTURE_METHOD V4L2_CAP_STREAMING
-#else
-#define DT3155_CAPTURE_METHOD V4L2_CAP_READWRITE
-#endif
-
-/* global initializers (for all boards) */
-#ifdef CONFIG_DT3155_CCIR
-static const u8 csr2_init = VT_50HZ;
-#define DT3155_CURRENT_NORM V4L2_STD_625_50
-static const unsigned int img_width = 768;
-static const unsigned int img_height = 576;
-static const unsigned int frames_per_sec = 25;
-static const struct v4l2_fmtdesc frame_std[] = {
- {
- .index = 0,
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- .flags = 0,
- .description = "CCIR/50Hz 8 bits gray",
- .pixelformat = V4L2_PIX_FMT_GREY,
- },
-};
-#else
-static const u8 csr2_init = VT_60HZ;
-#define DT3155_CURRENT_NORM V4L2_STD_525_60
-static const unsigned int img_width = 640;
-static const unsigned int img_height = 480;
-static const unsigned int frames_per_sec = 30;
-static const struct v4l2_fmtdesc frame_std[] = {
- {
- .index = 0,
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- .flags = 0,
- .description = "RS-170/60Hz 8 bits gray",
- .pixelformat = V4L2_PIX_FMT_GREY,
- },
-};
-#endif
-
-#define NUM_OF_FORMATS ARRAY_SIZE(frame_std)
-
-static u8 config_init = ACQ_MODE_EVEN;
-
-/**
- * read_i2c_reg - reads an internal i2c register
- *
- * @addr: dt3155 mmio base address
- * @index: index (internal address) of register to read
- * @data: pointer to byte the read data will be placed in
- *
- * returns: zero on success or error code
- *
- * This function starts reading the specified (by index) register
- * and busy waits for the process to finish. The result is placed
- * in a byte pointed by data.
- */
-static int
-read_i2c_reg(void __iomem *addr, u8 index, u8 *data)
-{
- u32 tmp = index;
-
- iowrite32((tmp<<17) | IIC_READ, addr + IIC_CSR2);
- mmiowb();
- udelay(45); /* wait at least 43 usec for NEW_CYCLE to clear */
- if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
- return -EIO; /* error: NEW_CYCLE not cleared */
- tmp = ioread32(addr + IIC_CSR1);
- if (tmp & DIRECT_ABORT) {
- /* reset DIRECT_ABORT bit */
- iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
- return -EIO; /* error: DIRECT_ABORT set */
- }
- *data = tmp>>24;
- return 0;
-}
-
-/**
- * write_i2c_reg - writes to an internal i2c register
- *
- * @addr: dt3155 mmio base address
- * @index: index (internal address) of register to read
- * @data: data to be written
- *
- * returns: zero on success or error code
- *
- * This function starts writting the specified (by index) register
- * and busy waits for the process to finish.
- */
-static int
-write_i2c_reg(void __iomem *addr, u8 index, u8 data)
-{
- u32 tmp = index;
-
- iowrite32((tmp<<17) | IIC_WRITE | data, addr + IIC_CSR2);
- mmiowb();
- udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
- if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
- return -EIO; /* error: NEW_CYCLE not cleared */
- if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
- /* reset DIRECT_ABORT bit */
- iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
- return -EIO; /* error: DIRECT_ABORT set */
- }
- return 0;
-}
-
-/**
- * write_i2c_reg_nowait - writes to an internal i2c register
- *
- * @addr: dt3155 mmio base address
- * @index: index (internal address) of register to read
- * @data: data to be written
- *
- * This function starts writting the specified (by index) register
- * and then returns.
- */
-static void write_i2c_reg_nowait(void __iomem *addr, u8 index, u8 data)
-{
- u32 tmp = index;
-
- iowrite32((tmp<<17) | IIC_WRITE | data, addr + IIC_CSR2);
- mmiowb();
-}
-
-/**
- * wait_i2c_reg - waits the read/write to finish
- *
- * @addr: dt3155 mmio base address
- *
- * returns: zero on success or error code
- *
- * This function waits reading/writting to finish.
- */
-static int wait_i2c_reg(void __iomem *addr)
-{
- if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
- udelay(65); /* wait at least 63 usec for NEW_CYCLE to clear */
- if (ioread32(addr + IIC_CSR2) & NEW_CYCLE)
- return -EIO; /* error: NEW_CYCLE not cleared */
- if (ioread32(addr + IIC_CSR1) & DIRECT_ABORT) {
- /* reset DIRECT_ABORT bit */
- iowrite32(DIRECT_ABORT, addr + IIC_CSR1);
- return -EIO; /* error: DIRECT_ABORT set */
- }
- return 0;
-}
-
-static int
-dt3155_start_acq(struct dt3155_priv *pd)
-{
- struct vb2_buffer *vb = pd->curr_buf;
- dma_addr_t dma_addr;
-
- dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
- iowrite32(dma_addr, pd->regs + EVEN_DMA_START);
- iowrite32(dma_addr + img_width, pd->regs + ODD_DMA_START);
- iowrite32(img_width, pd->regs + EVEN_DMA_STRIDE);
- iowrite32(img_width, pd->regs + ODD_DMA_STRIDE);
- /* enable interrupts, clear all irq flags */
- iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
- FLD_END_EVEN | FLD_END_ODD, pd->regs + INT_CSR);
- iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
- FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD,
- pd->regs + CSR1);
- wait_i2c_reg(pd->regs);
- write_i2c_reg(pd->regs, CONFIG, pd->config);
- write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE);
- write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_DONE);
-
- /* start the board */
- write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | BUSY_ODD);
- return 0; /* success */
-}
-
-/*
- * driver-specific callbacks (vb2_ops)
- */
-static int
-dt3155_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
- unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
-
-{
- struct dt3155_priv *pd = vb2_get_drv_priv(q);
- void *ret;
-
- if (*num_buffers == 0)
- *num_buffers = 1;
- *num_planes = 1;
- sizes[0] = img_width * img_height;
- if (pd->q->alloc_ctx[0])
- return 0;
- ret = vb2_dma_contig_init_ctx(&pd->pdev->dev);
- if (IS_ERR(ret))
- return PTR_ERR(ret);
- pd->q->alloc_ctx[0] = ret;
- return 0;
-}
-
-static void
-dt3155_wait_prepare(struct vb2_queue *q)
-{
- struct dt3155_priv *pd = vb2_get_drv_priv(q);
-
- mutex_unlock(pd->vdev.lock);
-}
-
-static void
-dt3155_wait_finish(struct vb2_queue *q)
-{
- struct dt3155_priv *pd = vb2_get_drv_priv(q);
-
- mutex_lock(pd->vdev.lock);
-}
-
-static int
-dt3155_buf_prepare(struct vb2_buffer *vb)
-{
- vb2_set_plane_payload(vb, 0, img_width * img_height);
- return 0;
-}
-
-static void
-dt3155_stop_streaming(struct vb2_queue *q)
-{
- struct dt3155_priv *pd = vb2_get_drv_priv(q);
- struct vb2_buffer *vb;
-
- spin_lock_irq(&pd->lock);
- while (!list_empty(&pd->dmaq)) {
- vb = list_first_entry(&pd->dmaq, typeof(*vb), done_entry);
- list_del(&vb->done_entry);
- vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irq(&pd->lock);
- msleep(45); /* irq hendler will stop the hardware */
-}
-
-static void
-dt3155_buf_queue(struct vb2_buffer *vb)
-{
- struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue);
-
- /* pd->q->streaming = 1 when dt3155_buf_queue() is invoked */
- spin_lock_irq(&pd->lock);
- if (pd->curr_buf)
- list_add_tail(&vb->done_entry, &pd->dmaq);
- else {
- pd->curr_buf = vb;
- dt3155_start_acq(pd);
- }
- spin_unlock_irq(&pd->lock);
-}
-/*
- * end driver-specific callbacks
- */
-
-static const struct vb2_ops q_ops = {
- .queue_setup = dt3155_queue_setup,
- .wait_prepare = dt3155_wait_prepare,
- .wait_finish = dt3155_wait_finish,
- .buf_prepare = dt3155_buf_prepare,
- .stop_streaming = dt3155_stop_streaming,
- .buf_queue = dt3155_buf_queue,
-};
-
-static irqreturn_t
-dt3155_irq_handler_even(int irq, void *dev_id)
-{
- struct dt3155_priv *ipd = dev_id;
- struct vb2_buffer *ivb;
- dma_addr_t dma_addr;
- u32 tmp;
-
- tmp = ioread32(ipd->regs + INT_CSR) & (FLD_START | FLD_END_ODD);
- if (!tmp)
- return IRQ_NONE; /* not our irq */
- if ((tmp & FLD_START) && !(tmp & FLD_END_ODD)) {
- iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START,
- ipd->regs + INT_CSR);
- ipd->field_count++;
- return IRQ_HANDLED; /* start of field irq */
- }
- if ((tmp & FLD_START) && (tmp & FLD_END_ODD))
- ipd->stats.start_before_end++;
- /* check for corrupted fields */
-/* write_i2c_reg(ipd->regs, EVEN_CSR, CSR_ERROR | CSR_DONE); */
-/* write_i2c_reg(ipd->regs, ODD_CSR, CSR_ERROR | CSR_DONE); */
- tmp = ioread32(ipd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD);
- if (tmp) {
- ipd->stats.corrupted_fields++;
- iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
- FLD_DN_ODD | FLD_DN_EVEN |
- CAP_CONT_EVEN | CAP_CONT_ODD,
- ipd->regs + CSR1);
- mmiowb();
- }
-
- spin_lock(&ipd->lock);
- if (ipd->curr_buf) {
- v4l2_get_timestamp(&ipd->curr_buf->v4l2_buf.timestamp);
- ipd->curr_buf->v4l2_buf.sequence = (ipd->field_count) >> 1;
- vb2_buffer_done(ipd->curr_buf, VB2_BUF_STATE_DONE);
- }
-
- if (!ipd->q->streaming || list_empty(&ipd->dmaq))
- goto stop_dma;
- ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry);
- list_del(&ivb->done_entry);
- ipd->curr_buf = ivb;
- dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0);
- iowrite32(dma_addr, ipd->regs + EVEN_DMA_START);
- iowrite32(dma_addr + img_width, ipd->regs + ODD_DMA_START);
- iowrite32(img_width, ipd->regs + EVEN_DMA_STRIDE);
- iowrite32(img_width, ipd->regs + ODD_DMA_STRIDE);
- mmiowb();
- /* enable interrupts, clear all irq flags */
- iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START |
- FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
- spin_unlock(&ipd->lock);
- return IRQ_HANDLED;
-
-stop_dma:
- ipd->curr_buf = NULL;
- /* stop the board */
- write_i2c_reg_nowait(ipd->regs, CSR2, ipd->csr2);
- iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN |
- FLD_DN_ODD | FLD_DN_EVEN, ipd->regs + CSR1);
- /* disable interrupts, clear all irq flags */
- iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR);
- spin_unlock(&ipd->lock);
- return IRQ_HANDLED;
-}
-
-static int
-dt3155_open(struct file *filp)
-{
- int ret = 0;
- struct dt3155_priv *pd = video_drvdata(filp);
-
- if (mutex_lock_interruptible(&pd->mux))
- return -ERESTARTSYS;
- if (!pd->users) {
- pd->q = kzalloc(sizeof(*pd->q), GFP_KERNEL);
- if (!pd->q) {
- ret = -ENOMEM;
- goto err_alloc_queue;
- }
- pd->q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- pd->q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- pd->q->io_modes = VB2_READ | VB2_MMAP;
- pd->q->ops = &q_ops;
- pd->q->mem_ops = &vb2_dma_contig_memops;
- pd->q->drv_priv = pd;
- pd->curr_buf = NULL;
- pd->field_count = 0;
- ret = vb2_queue_init(pd->q);
- if (ret < 0)
- goto err_request_irq;
- INIT_LIST_HEAD(&pd->dmaq);
- spin_lock_init(&pd->lock);
- /* disable all irqs, clear all irq flags */
- iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
- pd->regs + INT_CSR);
- ret = request_irq(pd->pdev->irq, dt3155_irq_handler_even,
- IRQF_SHARED, DT3155_NAME, pd);
- if (ret)
- goto err_request_irq;
- }
- pd->users++;
- mutex_unlock(&pd->mux);
- return 0; /* success */
-err_request_irq:
- kfree(pd->q);
- pd->q = NULL;
-err_alloc_queue:
- mutex_unlock(&pd->mux);
- return ret;
-}
-
-static int
-dt3155_release(struct file *filp)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- mutex_lock(&pd->mux);
- pd->users--;
- BUG_ON(pd->users < 0);
- if (!pd->users) {
- vb2_queue_release(pd->q);
- free_irq(pd->pdev->irq, pd);
- if (pd->q->alloc_ctx[0])
- vb2_dma_contig_cleanup_ctx(pd->q->alloc_ctx[0]);
- kfree(pd->q);
- pd->q = NULL;
- }
- mutex_unlock(&pd->mux);
- return 0;
-}
-
-static ssize_t
-dt3155_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
- ssize_t res;
-
- if (mutex_lock_interruptible(&pd->mux))
- return -ERESTARTSYS;
- res = vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK);
- mutex_unlock(&pd->mux);
- return res;
-}
-
-static unsigned int
-dt3155_poll(struct file *filp, struct poll_table_struct *polltbl)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
- unsigned int res;
-
- mutex_lock(&pd->mux);
- res = vb2_poll(pd->q, filp, polltbl);
- mutex_unlock(&pd->mux);
- return res;
-}
-
-static int
-dt3155_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
- int res;
-
- if (mutex_lock_interruptible(&pd->mux))
- return -ERESTARTSYS;
- res = vb2_mmap(pd->q, vma);
- mutex_unlock(&pd->mux);
- return res;
-}
-
-static const struct v4l2_file_operations dt3155_fops = {
- .owner = THIS_MODULE,
- .open = dt3155_open,
- .release = dt3155_release,
- .read = dt3155_read,
- .poll = dt3155_poll,
- .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
- .mmap = dt3155_mmap,
-};
-
-static int
-dt3155_ioc_streamon(struct file *filp, void *p, enum v4l2_buf_type type)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- return vb2_streamon(pd->q, type);
-}
-
-static int
-dt3155_ioc_streamoff(struct file *filp, void *p, enum v4l2_buf_type type)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- return vb2_streamoff(pd->q, type);
-}
-
-static int
-dt3155_ioc_querycap(struct file *filp, void *p, struct v4l2_capability *cap)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- strcpy(cap->driver, DT3155_NAME);
- strcpy(cap->card, DT3155_NAME " frame grabber");
- sprintf(cap->bus_info, "PCI:%s", pci_name(pd->pdev));
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
- DT3155_CAPTURE_METHOD;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
- return 0;
-}
-
-static int
-dt3155_ioc_enum_fmt_vid_cap(struct file *filp, void *p, struct v4l2_fmtdesc *f)
-{
- if (f->index >= NUM_OF_FORMATS)
- return -EINVAL;
- *f = frame_std[f->index];
- return 0;
-}
-
-static int
-dt3155_ioc_g_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
-{
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- f->fmt.pix.width = img_width;
- f->fmt.pix.height = img_height;
- f->fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
- f->fmt.pix.field = V4L2_FIELD_NONE;
- f->fmt.pix.bytesperline = f->fmt.pix.width;
- f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height;
- f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
- return 0;
-}
-
-static int
-dt3155_ioc_try_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
-{
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (f->fmt.pix.width == img_width &&
- f->fmt.pix.height == img_height &&
- f->fmt.pix.pixelformat == V4L2_PIX_FMT_GREY &&
- f->fmt.pix.field == V4L2_FIELD_NONE &&
- f->fmt.pix.bytesperline == f->fmt.pix.width &&
- f->fmt.pix.sizeimage == f->fmt.pix.width * f->fmt.pix.height)
- return 0;
- else
- return -EINVAL;
-}
-
-static int
-dt3155_ioc_s_fmt_vid_cap(struct file *filp, void *p, struct v4l2_format *f)
-{
- return dt3155_ioc_g_fmt_vid_cap(filp, p, f);
-}
-
-static int
-dt3155_ioc_reqbufs(struct file *filp, void *p, struct v4l2_requestbuffers *b)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- return vb2_reqbufs(pd->q, b);
-}
-
-static int
-dt3155_ioc_querybuf(struct file *filp, void *p, struct v4l2_buffer *b)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- return vb2_querybuf(pd->q, b);
-}
-
-static int
-dt3155_ioc_qbuf(struct file *filp, void *p, struct v4l2_buffer *b)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- return vb2_qbuf(pd->q, b);
-}
-
-static int
-dt3155_ioc_dqbuf(struct file *filp, void *p, struct v4l2_buffer *b)
-{
- struct dt3155_priv *pd = video_drvdata(filp);
-
- return vb2_dqbuf(pd->q, b, filp->f_flags & O_NONBLOCK);
-}
-
-static int
-dt3155_ioc_querystd(struct file *filp, void *p, v4l2_std_id *norm)
-{
- *norm = DT3155_CURRENT_NORM;
- return 0;
-}
-
-static int
-dt3155_ioc_g_std(struct file *filp, void *p, v4l2_std_id *norm)
-{
- *norm = DT3155_CURRENT_NORM;
- return 0;
-}
-
-static int
-dt3155_ioc_s_std(struct file *filp, void *p, v4l2_std_id norm)
-{
- if (norm & DT3155_CURRENT_NORM)
- return 0;
- return -EINVAL;
-}
-
-static int
-dt3155_ioc_enum_input(struct file *filp, void *p, struct v4l2_input *input)
-{
- if (input->index)
- return -EINVAL;
- strcpy(input->name, "Coax in");
- input->type = V4L2_INPUT_TYPE_CAMERA;
- /*
- * FIXME: input->std = 0 according to v4l2 API
- * VIDIOC_G_STD, VIDIOC_S_STD, VIDIOC_QUERYSTD and VIDIOC_ENUMSTD
- * should return -EINVAL
- */
- input->std = DT3155_CURRENT_NORM;
- input->status = 0;/* FIXME: add sync detection & V4L2_IN_ST_NO_H_LOCK */
- return 0;
-}
-
-static int
-dt3155_ioc_g_input(struct file *filp, void *p, unsigned int *i)
-{
- *i = 0;
- return 0;
-}
-
-static int
-dt3155_ioc_s_input(struct file *filp, void *p, unsigned int i)
-{
- if (i)
- return -EINVAL;
- return 0;
-}
-
-static int
-dt3155_ioc_g_parm(struct file *filp, void *p, struct v4l2_streamparm *parms)
-{
- if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- parms->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- parms->parm.capture.capturemode = 0;
- parms->parm.capture.timeperframe.numerator = 1001;
- parms->parm.capture.timeperframe.denominator = frames_per_sec * 1000;
- parms->parm.capture.extendedmode = 0;
- parms->parm.capture.readbuffers = 1; /* FIXME: 2 buffers? */
- return 0;
-}
-
-static int
-dt3155_ioc_s_parm(struct file *filp, void *p, struct v4l2_streamparm *parms)
-{
- if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- parms->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
- parms->parm.capture.capturemode = 0;
- parms->parm.capture.timeperframe.numerator = 1001;
- parms->parm.capture.timeperframe.denominator = frames_per_sec * 1000;
- parms->parm.capture.extendedmode = 0;
- parms->parm.capture.readbuffers = 1; /* FIXME: 2 buffers? */
- return 0;
-}
-
-static const struct v4l2_ioctl_ops dt3155_ioctl_ops = {
- .vidioc_streamon = dt3155_ioc_streamon,
- .vidioc_streamoff = dt3155_ioc_streamoff,
- .vidioc_querycap = dt3155_ioc_querycap,
-/*
- .vidioc_g_priority = dt3155_ioc_g_priority,
- .vidioc_s_priority = dt3155_ioc_s_priority,
-*/
- .vidioc_enum_fmt_vid_cap = dt3155_ioc_enum_fmt_vid_cap,
- .vidioc_try_fmt_vid_cap = dt3155_ioc_try_fmt_vid_cap,
- .vidioc_g_fmt_vid_cap = dt3155_ioc_g_fmt_vid_cap,
- .vidioc_s_fmt_vid_cap = dt3155_ioc_s_fmt_vid_cap,
- .vidioc_reqbufs = dt3155_ioc_reqbufs,
- .vidioc_querybuf = dt3155_ioc_querybuf,
- .vidioc_qbuf = dt3155_ioc_qbuf,
- .vidioc_dqbuf = dt3155_ioc_dqbuf,
- .vidioc_querystd = dt3155_ioc_querystd,
- .vidioc_g_std = dt3155_ioc_g_std,
- .vidioc_s_std = dt3155_ioc_s_std,
- .vidioc_enum_input = dt3155_ioc_enum_input,
- .vidioc_g_input = dt3155_ioc_g_input,
- .vidioc_s_input = dt3155_ioc_s_input,
-/*
- .vidioc_queryctrl = dt3155_ioc_queryctrl,
- .vidioc_g_ctrl = dt3155_ioc_g_ctrl,
- .vidioc_s_ctrl = dt3155_ioc_s_ctrl,
- .vidioc_querymenu = dt3155_ioc_querymenu,
- .vidioc_g_ext_ctrls = dt3155_ioc_g_ext_ctrls,
- .vidioc_s_ext_ctrls = dt3155_ioc_s_ext_ctrls,
-*/
- .vidioc_g_parm = dt3155_ioc_g_parm,
- .vidioc_s_parm = dt3155_ioc_s_parm,
-/*
- .vidioc_cropcap = dt3155_ioc_cropcap,
- .vidioc_g_crop = dt3155_ioc_g_crop,
- .vidioc_s_crop = dt3155_ioc_s_crop,
- .vidioc_enum_framesizes = dt3155_ioc_enum_framesizes,
- .vidioc_enum_frameintervals = dt3155_ioc_enum_frameintervals,
-*/
-};
-
-static int
-dt3155_init_board(struct pci_dev *pdev)
-{
- struct dt3155_priv *pd = pci_get_drvdata(pdev);
- void *buf_cpu;
- dma_addr_t buf_dma;
- int i;
- u8 tmp;
-
- pci_set_master(pdev); /* dt3155 needs it */
-
- /* resetting the adapter */
- iowrite32(FLD_CRPT_ODD | FLD_CRPT_EVEN | FLD_DN_ODD | FLD_DN_EVEN,
- pd->regs + CSR1);
- mmiowb();
- msleep(20);
-
- /* initializing adaper registers */
- iowrite32(FIFO_EN | SRST, pd->regs + CSR1);
- mmiowb();
- iowrite32(0xEEEEEE01, pd->regs + EVEN_PIXEL_FMT);
- iowrite32(0xEEEEEE01, pd->regs + ODD_PIXEL_FMT);
- iowrite32(0x00000020, pd->regs + FIFO_TRIGER);
- iowrite32(0x00000103, pd->regs + XFER_MODE);
- iowrite32(0, pd->regs + RETRY_WAIT_CNT);
- iowrite32(0, pd->regs + INT_CSR);
- iowrite32(1, pd->regs + EVEN_FLD_MASK);
- iowrite32(1, pd->regs + ODD_FLD_MASK);
- iowrite32(0, pd->regs + MASK_LENGTH);
- iowrite32(0x0005007C, pd->regs + FIFO_FLAG_CNT);
- iowrite32(0x01010101, pd->regs + IIC_CLK_DUR);
- mmiowb();
-
- /* verifying that we have a DT3155 board (not just a SAA7116 chip) */
- read_i2c_reg(pd->regs, DT_ID, &tmp);
- if (tmp != DT3155_ID)
- return -ENODEV;
-
- /* initialize AD LUT */
- write_i2c_reg(pd->regs, AD_ADDR, 0);
- for (i = 0; i < 256; i++)
- write_i2c_reg(pd->regs, AD_LUT, i);
-
- /* initialize ADC references */
- /* FIXME: pos_ref & neg_ref depend on VT_50HZ */
- write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
- write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
- write_i2c_reg(pd->regs, AD_ADDR, AD_POS_REF);
- write_i2c_reg(pd->regs, AD_CMD, 34);
- write_i2c_reg(pd->regs, AD_ADDR, AD_NEG_REF);
- write_i2c_reg(pd->regs, AD_CMD, 0);
-
- /* initialize PM LUT */
- write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM);
- for (i = 0; i < 256; i++) {
- write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
- write_i2c_reg(pd->regs, PM_LUT_DATA, i);
- }
- write_i2c_reg(pd->regs, CONFIG, pd->config | PM_LUT_PGM | PM_LUT_SEL);
- for (i = 0; i < 256; i++) {
- write_i2c_reg(pd->regs, PM_LUT_ADDR, i);
- write_i2c_reg(pd->regs, PM_LUT_DATA, i);
- }
- write_i2c_reg(pd->regs, CONFIG, pd->config); /* ACQ_MODE_EVEN */
-
- /* select channel 1 for input and set sync level */
- write_i2c_reg(pd->regs, AD_ADDR, AD_CMD_REG);
- write_i2c_reg(pd->regs, AD_CMD, VIDEO_CNL_1 | SYNC_CNL_1 | SYNC_LVL_3);
-
- /* allocate memory, and initialize the DMA machine */
- buf_cpu = dma_alloc_coherent(&pdev->dev, DT3155_BUF_SIZE, &buf_dma,
- GFP_KERNEL);
- if (!buf_cpu)
- return -ENOMEM;
- iowrite32(buf_dma, pd->regs + EVEN_DMA_START);
- iowrite32(buf_dma, pd->regs + ODD_DMA_START);
- iowrite32(0, pd->regs + EVEN_DMA_STRIDE);
- iowrite32(0, pd->regs + ODD_DMA_STRIDE);
-
- /* Perform a pseudo even field acquire */
- iowrite32(FIFO_EN | SRST | CAP_CONT_ODD, pd->regs + CSR1);
- write_i2c_reg(pd->regs, CSR2, pd->csr2 | SYNC_SNTL);
- write_i2c_reg(pd->regs, CONFIG, pd->config);
- write_i2c_reg(pd->regs, EVEN_CSR, CSR_SNGL);
- write_i2c_reg(pd->regs, CSR2, pd->csr2 | BUSY_EVEN | SYNC_SNTL);
- msleep(100);
- read_i2c_reg(pd->regs, CSR2, &tmp);
- write_i2c_reg(pd->regs, EVEN_CSR, CSR_ERROR | CSR_SNGL | CSR_DONE);
- write_i2c_reg(pd->regs, ODD_CSR, CSR_ERROR | CSR_SNGL | CSR_DONE);
- write_i2c_reg(pd->regs, CSR2, pd->csr2);
- iowrite32(FIFO_EN | SRST | FLD_DN_EVEN | FLD_DN_ODD, pd->regs + CSR1);
-
- /* deallocate memory */
- dma_free_coherent(&pdev->dev, DT3155_BUF_SIZE, buf_cpu, buf_dma);
- if (tmp & BUSY_EVEN)
- return -EIO;
- return 0;
-}
-
-static struct video_device dt3155_vdev = {
- .name = DT3155_NAME,
- .fops = &dt3155_fops,
- .ioctl_ops = &dt3155_ioctl_ops,
- .minor = -1,
- .release = video_device_release_empty,
- .tvnorms = DT3155_CURRENT_NORM,
-};
-
-/* same as in drivers/base/dma-coherent.c */
-struct dma_coherent_mem {
- void *virt_base;
- dma_addr_t device_base;
- int size;
- int flags;
- unsigned long *bitmap;
-};
-
-static int
-dt3155_alloc_coherent(struct device *dev, size_t size, int flags)
-{
- struct dma_coherent_mem *mem;
- dma_addr_t dev_base;
- int pages = size >> PAGE_SHIFT;
- int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-
- if ((flags & DMA_MEMORY_MAP) == 0)
- goto out;
- if (!size)
- goto out;
- if (dev->dma_mem)
- goto out;
-
- mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- if (!mem)
- goto out;
- mem->virt_base = dma_alloc_coherent(dev, size, &dev_base,
- DT3155_COH_FLAGS);
- if (!mem->virt_base)
- goto err_alloc_coherent;
- mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!mem->bitmap)
- goto err_bitmap;
-
- /* coherent_dma_mask is already set to 32 bits */
- mem->device_base = dev_base;
- mem->size = pages;
- mem->flags = flags;
- dev->dma_mem = mem;
- return DMA_MEMORY_MAP;
-
-err_bitmap:
- dma_free_coherent(dev, size, mem->virt_base, dev_base);
-err_alloc_coherent:
- kfree(mem);
-out:
- return 0;
-}
-
-static void
-dt3155_free_coherent(struct device *dev)
-{
- struct dma_coherent_mem *mem = dev->dma_mem;
-
- if (!mem)
- return;
- dev->dma_mem = NULL;
- dma_free_coherent(dev, mem->size << PAGE_SHIFT,
- mem->virt_base, mem->device_base);
- kfree(mem->bitmap);
- kfree(mem);
-}
-
-static int
-dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- int err;
- struct dt3155_priv *pd;
-
- err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
- if (err)
- return -ENODEV;
- pd = devm_kzalloc(&pdev->dev, sizeof(*pd), GFP_KERNEL);
- if (!pd)
- return -ENOMEM;
-
- pd->vdev = dt3155_vdev;
- pci_set_drvdata(pdev, pd); /* for use in dt3155_remove() */
- video_set_drvdata(&pd->vdev, pd); /* for use in video_fops */
- pd->users = 0;
- pd->pdev = pdev;
- INIT_LIST_HEAD(&pd->dmaq);
- mutex_init(&pd->mux);
- pd->vdev.lock = &pd->mux; /* for locking v4l2_file_operations */
- spin_lock_init(&pd->lock);
- pd->csr2 = csr2_init;
- pd->config = config_init;
- err = pci_enable_device(pdev);
- if (err)
- return err;
- err = pci_request_region(pdev, 0, pci_name(pdev));
- if (err)
- goto err_req_region;
- pd->regs = pci_iomap(pdev, 0, pci_resource_len(pd->pdev, 0));
- if (!pd->regs) {
- err = -ENOMEM;
- goto err_pci_iomap;
- }
- err = dt3155_init_board(pdev);
- if (err)
- goto err_init_board;
- err = video_register_device(&pd->vdev, VFL_TYPE_GRABBER, -1);
- if (err)
- goto err_init_board;
- if (dt3155_alloc_coherent(&pdev->dev, DT3155_CHUNK_SIZE,
- DMA_MEMORY_MAP))
- dev_info(&pdev->dev, "preallocated 8 buffers\n");
- dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev.minor);
- return 0; /* success */
-
-err_init_board:
- pci_iounmap(pdev, pd->regs);
-err_pci_iomap:
- pci_release_region(pdev, 0);
-err_req_region:
- pci_disable_device(pdev);
- return err;
-}
-
-static void
-dt3155_remove(struct pci_dev *pdev)
-{
- struct dt3155_priv *pd = pci_get_drvdata(pdev);
-
- dt3155_free_coherent(&pdev->dev);
- video_unregister_device(&pd->vdev);
- pci_iounmap(pdev, pd->regs);
- pci_release_region(pdev, 0);
- pci_disable_device(pdev);
-}
-
-static const struct pci_device_id pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, DT3155_DEVICE_ID) },
- { 0, /* zero marks the end */ },
-};
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-static struct pci_driver pci_driver = {
- .name = DT3155_NAME,
- .id_table = pci_ids,
- .probe = dt3155_probe,
- .remove = dt3155_remove,
-};
-
-module_pci_driver(pci_driver);
-
-MODULE_DESCRIPTION("video4linux pci-driver for dt3155 frame grabber");
-MODULE_AUTHOR("Marin Mitov <mitov@issp.bas.bg>");
-MODULE_VERSION(DT3155_VERSION);
-MODULE_LICENSE("GPL");
+++ /dev/null
-/***************************************************************************
- * Copyright (C) 2006-2010 by Marin Mitov *
- * mitov@issp.bas.bg *
- * *
- * 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 *
- * (at your option) 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. *
- ***************************************************************************/
-
-/* DT3155 header file */
-#ifndef _DT3155_H_
-#define _DT3155_H_
-
-#ifdef __KERNEL__
-
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-
-#define DT3155_NAME "dt3155"
-#define DT3155_VER_MAJ 1
-#define DT3155_VER_MIN 1
-#define DT3155_VER_EXT 0
-#define DT3155_VERSION __stringify(DT3155_VER_MAJ) "." \
- __stringify(DT3155_VER_MIN) "." \
- __stringify(DT3155_VER_EXT)
-
-/* DT3155 Base Register offsets (memory mapped) */
-#define EVEN_DMA_START 0x00
-#define ODD_DMA_START 0x0C
-#define EVEN_DMA_STRIDE 0x18
-#define ODD_DMA_STRIDE 0x24
-#define EVEN_PIXEL_FMT 0x30
-#define ODD_PIXEL_FMT 0x34
-#define FIFO_TRIGER 0x38
-#define XFER_MODE 0x3C
-#define CSR1 0x40
-#define RETRY_WAIT_CNT 0x44
-#define INT_CSR 0x48
-#define EVEN_FLD_MASK 0x4C
-#define ODD_FLD_MASK 0x50
-#define MASK_LENGTH 0x54
-#define FIFO_FLAG_CNT 0x58
-#define IIC_CLK_DUR 0x5C
-#define IIC_CSR1 0x60
-#define IIC_CSR2 0x64
-
-/* DT3155 Internal Registers indexes (i2c/IIC mapped) */
-#define CSR2 0x10
-#define EVEN_CSR 0x11
-#define ODD_CSR 0x12
-#define CONFIG 0x13
-#define DT_ID 0x1F
-#define X_CLIP_START 0x20
-#define Y_CLIP_START 0x22
-#define X_CLIP_END 0x24
-#define Y_CLIP_END 0x26
-#define AD_ADDR 0x30
-#define AD_LUT 0x31
-#define AD_CMD 0x32
-#define DIG_OUT 0x40
-#define PM_LUT_ADDR 0x50
-#define PM_LUT_DATA 0x51
-
-/* AD command register values */
-#define AD_CMD_REG 0x00
-#define AD_POS_REF 0x01
-#define AD_NEG_REF 0x02
-
-/* CSR1 bit masks */
-#define CRPT_DIS 0x00004000
-#define FLD_CRPT_ODD 0x00000200
-#define FLD_CRPT_EVEN 0x00000100
-#define FIFO_EN 0x00000080
-#define SRST 0x00000040
-#define FLD_DN_ODD 0x00000020
-#define FLD_DN_EVEN 0x00000010
-/* These should not be used.
- * Use CAP_CONT_ODD/EVEN instead
-#define CAP_SNGL_ODD 0x00000008
-#define CAP_SNGL_EVEN 0x00000004
-*/
-#define CAP_CONT_ODD 0x00000002
-#define CAP_CONT_EVEN 0x00000001
-
-/* INT_CSR bit masks */
-#define FLD_START_EN 0x00000400
-#define FLD_END_ODD_EN 0x00000200
-#define FLD_END_EVEN_EN 0x00000100
-#define FLD_START 0x00000004
-#define FLD_END_ODD 0x00000002
-#define FLD_END_EVEN 0x00000001
-
-/* IIC_CSR1 bit masks */
-#define DIRECT_ABORT 0x00000200
-
-/* IIC_CSR2 bit masks */
-#define NEW_CYCLE 0x01000000
-#define DIR_RD 0x00010000
-#define IIC_READ 0x01010000
-#define IIC_WRITE 0x01000000
-
-/* CSR2 bit masks */
-#define DISP_PASS 0x40
-#define BUSY_ODD 0x20
-#define BUSY_EVEN 0x10
-#define SYNC_PRESENT 0x08
-#define VT_50HZ 0x04
-#define SYNC_SNTL 0x02
-#define CHROM_FILT 0x01
-#define VT_60HZ 0x00
-
-/* CSR_EVEN/ODD bit masks */
-#define CSR_ERROR 0x04
-#define CSR_SNGL 0x02
-#define CSR_DONE 0x01
-
-/* CONFIG bit masks */
-#define PM_LUT_PGM 0x80
-#define PM_LUT_SEL 0x40
-#define CLIP_EN 0x20
-#define HSCALE_EN 0x10
-#define EXT_TRIG_UP 0x0C
-#define EXT_TRIG_DOWN 0x04
-#define ACQ_MODE_NEXT 0x02
-#define ACQ_MODE_ODD 0x01
-#define ACQ_MODE_EVEN 0x00
-
-/* AD_CMD bit masks */
-#define VIDEO_CNL_1 0x00
-#define VIDEO_CNL_2 0x40
-#define VIDEO_CNL_3 0x80
-#define VIDEO_CNL_4 0xC0
-#define SYNC_CNL_1 0x00
-#define SYNC_CNL_2 0x10
-#define SYNC_CNL_3 0x20
-#define SYNC_CNL_4 0x30
-#define SYNC_LVL_1 0x00
-#define SYNC_LVL_2 0x04
-#define SYNC_LVL_3 0x08
-#define SYNC_LVL_4 0x0C
-
-/* DT3155 identificator */
-#define DT3155_ID 0x20
-
-#ifdef CONFIG_DT3155_CCIR
-#define DMA_STRIDE 768
-#else
-#define DMA_STRIDE 640
-#endif
-
-/**
- * struct dt3155_stats - statistics structure
- *
- * @free_bufs_empty: no free image buffers
- * @corrupted_fields: corrupted fields
- * @dma_map_failed: dma mapping failed
- * @start_before_end: new started before old ended
- */
-struct dt3155_stats {
- int free_bufs_empty;
- int corrupted_fields;
- int dma_map_failed;
- int start_before_end;
-};
-
-/* per board private data structure */
-/**
- * struct dt3155_priv - private data structure
- *
- * @vdev: video_device structure
- * @pdev: pointer to pci_dev structure
- * @q pointer to vb2_queue structure
- * @curr_buf: pointer to curren buffer
- * @mux: mutex to protect the instance
- * @dmaq queue for dma buffers
- * @lock spinlock for dma queue
- * @field_count fields counter
- * @stats: statistics structure
- * @users open count
- * @regs: local copy of mmio base register
- * @csr2: local copy of csr2 register
- * @config: local copy of config register
- */
-struct dt3155_priv {
- struct video_device vdev;
- struct pci_dev *pdev;
- struct vb2_queue *q;
- struct vb2_buffer *curr_buf;
- struct mutex mux;
- struct list_head dmaq;
- spinlock_t lock;
- unsigned int field_count;
- struct dt3155_stats stats;
- void __iomem *regs;
- int users;
- u8 csr2, config;
-};
-
-#endif /* __KERNEL__ */
-
-#endif /* _DT3155_H_ */
int (*power)(struct v4l2_subdev *sd, int on);
u32 max_flash_timeout; /* flash light timeout in us */
- u32 max_flash_intensity; /* led intensity, flash mode */
- u32 max_torch_intensity; /* led intensity, torch mode */
- u32 max_indicator_intensity; /* indicator led intensity */
+ u32 max_flash_intensity; /* led intensity, flash mode, mA */
+ u32 max_torch_intensity; /* led intensity, torch mode, mA */
+ u32 max_indicator_intensity; /* indicator led intensity, uA */
+
+ struct gpio_desc *enable_gpio; /* for device-tree based boot */
};
#define to_adp1653_flash(sd) container_of(sd, struct adp1653_flash, subdev)
* @base: struct of_endpoint containing port, id, and local of_node
* @bus_type: bus type
* @bus: bus configuration data structure
- * @head: list head for this structure
+ * @link_frequencies: array of supported link frequencies
+ * @nr_of_link_frequencies: number of elements in link_frequenccies array
*/
struct v4l2_of_endpoint {
struct of_endpoint base;
+ /* Fields below this line will be zeroed by v4l2_of_parse_endpoint() */
enum v4l2_mbus_type bus_type;
union {
struct v4l2_of_bus_parallel parallel;
struct v4l2_of_bus_mipi_csi2 mipi_csi2;
} bus;
- struct list_head head;
+ u64 *link_frequencies;
+ unsigned int nr_of_link_frequencies;
};
/**
#ifdef CONFIG_OF
int v4l2_of_parse_endpoint(const struct device_node *node,
struct v4l2_of_endpoint *endpoint);
+struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint(
+ const struct device_node *node);
+void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint);
int v4l2_of_parse_link(const struct device_node *node,
struct v4l2_of_link *link);
void v4l2_of_put_link(struct v4l2_of_link *link);
return -ENOSYS;
}
+static inline struct v4l2_of_endpoint *v4l2_of_alloc_parse_endpoint(
+ const struct device_node *node)
+{
+ return NULL;
+}
+
+static inline void v4l2_of_free_endpoint(struct v4l2_of_endpoint *endpoint)
+{
+}
+
static inline int v4l2_of_parse_link(const struct device_node *node,
struct v4l2_of_link *link)
{
g_dv_timings(): Get custom dv timings in the sub device.
- enum_mbus_fmt: enumerate pixel formats, provided by a video data source
-
- g_mbus_fmt: get the current pixel format, provided by a video data source
-
- try_mbus_fmt: try to set a pixel format on a video data source
-
- s_mbus_fmt: set a pixel format on a video data source
-
g_mbus_config: get supported mediabus configurations
s_mbus_config: set a certain mediabus configuration. This operation is added
struct v4l2_dv_timings *timings);
int (*query_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
- int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
- u32 *code);
- int (*g_mbus_fmt)(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt);
- int (*try_mbus_fmt)(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt);
- int (*s_mbus_fmt)(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *fmt);
int (*g_mbus_config)(struct v4l2_subdev *sd,
struct v4l2_mbus_config *cfg);
int (*s_mbus_config)(struct v4l2_subdev *sd,