Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (42 commits) [media] media: vb2: correct queue initialization order [media] media: vb2: fix incorrect v4l2_buffer->flags handling [media] s5p-fimc: Add support for the buffer timestamps and sequence [media] s5p-fimc: Fix bytesperline and plane payload setup [media] s5p-fimc: Do not allow changing format after REQBUFS [media] s5p-fimc: Fix FIMC3 pixel limits on Exynos4 [media] tda18271: update tda18271c2_rf_cal as per NXP's rev.04 datasheet [media] tda18271: update tda18271_rf_band as per NXP's rev.04 datasheet [media] tda18271: fix bad calculation of main post divider byte [media] tda18271: prog_cal and prog_tab variables should be s32, not u8 [media] tda18271: fix calculation bug in tda18271_rf_tracking_filters_init [media] omap3isp: queue: Don't corrupt buf->npages when get_user_pages() fails [media] v4l: Don't register media entities for subdev device nodes [media] omap3isp: Don't increment node entity use count when poweron fails [media] omap3isp: lane shifter support [media] omap3isp: ccdc: support Y10/12, 8-bit bayer fmts [media] media: add missing 8-bit bayer formats and Y12 [media] v4l: add V4L2_PIX_FMT_Y12 format cx23885: Fix stv0367 Kconfig dependency [media] omap3isp: Use isp xclk defines ... Fix up trivial conflict (spelink errurs) in drivers/media/video/omap3isp/isp.c
This commit is contained in:
commit
7fcaa9aaea
37 changed files with 512 additions and 152 deletions
|
@ -294,6 +294,7 @@
|
|||
<!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
|
||||
<!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
|
||||
<!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
|
||||
<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
|
||||
<!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
|
||||
<!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
|
||||
<!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<varlistentry>
|
||||
<term><parameter>request</parameter></term>
|
||||
<listitem>
|
||||
<para>MEDIA_IOC_ENUM_LINKS</para>
|
||||
<para>MEDIA_IOC_SETUP_LINK</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
|
79
Documentation/DocBook/v4l/pixfmt-y12.xml
Normal file
79
Documentation/DocBook/v4l/pixfmt-y12.xml
Normal file
|
@ -0,0 +1,79 @@
|
|||
<refentry id="V4L2-PIX-FMT-Y12">
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_Y12 ('Y12 ')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname><constant>V4L2_PIX_FMT_Y12</constant></refname>
|
||||
<refpurpose>Grey-scale image</refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>This is a grey-scale image with a depth of 12 bits per pixel. Pixels
|
||||
are stored in 16-bit words with unused high bits padded with 0. The least
|
||||
significant byte is stored at lower memory addresses (little-endian).</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_Y12</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="9" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>Y'<subscript>00low</subscript></entry>
|
||||
<entry>Y'<subscript>00high</subscript></entry>
|
||||
<entry>Y'<subscript>01low</subscript></entry>
|
||||
<entry>Y'<subscript>01high</subscript></entry>
|
||||
<entry>Y'<subscript>02low</subscript></entry>
|
||||
<entry>Y'<subscript>02high</subscript></entry>
|
||||
<entry>Y'<subscript>03low</subscript></entry>
|
||||
<entry>Y'<subscript>03high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>Y'<subscript>10low</subscript></entry>
|
||||
<entry>Y'<subscript>10high</subscript></entry>
|
||||
<entry>Y'<subscript>11low</subscript></entry>
|
||||
<entry>Y'<subscript>11high</subscript></entry>
|
||||
<entry>Y'<subscript>12low</subscript></entry>
|
||||
<entry>Y'<subscript>12high</subscript></entry>
|
||||
<entry>Y'<subscript>13low</subscript></entry>
|
||||
<entry>Y'<subscript>13high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 16:</entry>
|
||||
<entry>Y'<subscript>20low</subscript></entry>
|
||||
<entry>Y'<subscript>20high</subscript></entry>
|
||||
<entry>Y'<subscript>21low</subscript></entry>
|
||||
<entry>Y'<subscript>21high</subscript></entry>
|
||||
<entry>Y'<subscript>22low</subscript></entry>
|
||||
<entry>Y'<subscript>22high</subscript></entry>
|
||||
<entry>Y'<subscript>23low</subscript></entry>
|
||||
<entry>Y'<subscript>23high</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 24:</entry>
|
||||
<entry>Y'<subscript>30low</subscript></entry>
|
||||
<entry>Y'<subscript>30high</subscript></entry>
|
||||
<entry>Y'<subscript>31low</subscript></entry>
|
||||
<entry>Y'<subscript>31high</subscript></entry>
|
||||
<entry>Y'<subscript>32low</subscript></entry>
|
||||
<entry>Y'<subscript>32high</subscript></entry>
|
||||
<entry>Y'<subscript>33low</subscript></entry>
|
||||
<entry>Y'<subscript>33high</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -696,6 +696,7 @@ information.</para>
|
|||
&sub-packed-yuv;
|
||||
&sub-grey;
|
||||
&sub-y10;
|
||||
&sub-y12;
|
||||
&sub-y16;
|
||||
&sub-yuyv;
|
||||
&sub-uyvy;
|
||||
|
|
|
@ -456,6 +456,23 @@
|
|||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-MBUS-FMT-SGBRG8-1X8">
|
||||
<entry>V4L2_MBUS_FMT_SGBRG8_1X8</entry>
|
||||
<entry>0x3013</entry>
|
||||
<entry></entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>g<subscript>7</subscript></entry>
|
||||
<entry>g<subscript>6</subscript></entry>
|
||||
<entry>g<subscript>5</subscript></entry>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
<entry>g<subscript>2</subscript></entry>
|
||||
<entry>g<subscript>1</subscript></entry>
|
||||
<entry>g<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-MBUS-FMT-SGRBG8-1X8">
|
||||
<entry>V4L2_MBUS_FMT_SGRBG8_1X8</entry>
|
||||
<entry>0x3002</entry>
|
||||
|
@ -473,6 +490,23 @@
|
|||
<entry>g<subscript>1</subscript></entry>
|
||||
<entry>g<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-MBUS-FMT-SRGGB8-1X8">
|
||||
<entry>V4L2_MBUS_FMT_SRGGB8_1X8</entry>
|
||||
<entry>0x3014</entry>
|
||||
<entry></entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>r<subscript>7</subscript></entry>
|
||||
<entry>r<subscript>6</subscript></entry>
|
||||
<entry>r<subscript>5</subscript></entry>
|
||||
<entry>r<subscript>4</subscript></entry>
|
||||
<entry>r<subscript>3</subscript></entry>
|
||||
<entry>r<subscript>2</subscript></entry>
|
||||
<entry>r<subscript>1</subscript></entry>
|
||||
<entry>r<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-MBUS-FMT-SBGGR10-DPCM8-1X8">
|
||||
<entry>V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8</entry>
|
||||
<entry>0x300b</entry>
|
||||
|
@ -2159,6 +2193,31 @@
|
|||
<entry>u<subscript>1</subscript></entry>
|
||||
<entry>u<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-MBUS-FMT-Y12-1X12">
|
||||
<entry>V4L2_MBUS_FMT_Y12_1X12</entry>
|
||||
<entry>0x2013</entry>
|
||||
<entry></entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>-</entry>
|
||||
<entry>y<subscript>11</subscript></entry>
|
||||
<entry>y<subscript>10</subscript></entry>
|
||||
<entry>y<subscript>9</subscript></entry>
|
||||
<entry>y<subscript>8</subscript></entry>
|
||||
<entry>y<subscript>7</subscript></entry>
|
||||
<entry>y<subscript>6</subscript></entry>
|
||||
<entry>y<subscript>5</subscript></entry>
|
||||
<entry>y<subscript>4</subscript></entry>
|
||||
<entry>y<subscript>3</subscript></entry>
|
||||
<entry>y<subscript>2</subscript></entry>
|
||||
<entry>y<subscript>1</subscript></entry>
|
||||
<entry>y<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-MBUS-FMT-UYVY8-1X16">
|
||||
<entry>V4L2_MBUS_FMT_UYVY8_1X16</entry>
|
||||
<entry>0x200f</entry>
|
||||
|
|
|
@ -37,7 +37,7 @@ Generic scaling / cropping scheme
|
|||
-1'-
|
||||
|
||||
In the above chart minuses and slashes represent "real" data amounts, points and
|
||||
accents represent "useful" data, basically, CEU scaled amd cropped output,
|
||||
accents represent "useful" data, basically, CEU scaled and cropped output,
|
||||
mapped back onto the client's source plane.
|
||||
|
||||
Such a configuration can be produced by user requests:
|
||||
|
@ -65,7 +65,7 @@ Do not touch input rectangle - it is already optimal.
|
|||
|
||||
1. Calculate current sensor scales:
|
||||
|
||||
scale_s = ((3') - (3)) / ((2') - (2))
|
||||
scale_s = ((2') - (2)) / ((3') - (3))
|
||||
|
||||
2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
|
||||
current sensor scales onto input window - this is user S_CROP:
|
||||
|
@ -80,7 +80,7 @@ window:
|
|||
4. Calculate sensor output window by applying combined scales to real input
|
||||
window:
|
||||
|
||||
width_s_out = ((2') - (2)) / scale_comb
|
||||
width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
|
||||
|
||||
5. Apply iterative sensor S_FMT for sensor output window.
|
||||
|
||||
|
|
|
@ -533,16 +533,7 @@ int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
|
|||
if (tda_fail(ret))
|
||||
goto fail;
|
||||
|
||||
regs[R_MPD] = (0x77 & pd);
|
||||
|
||||
switch (priv->mode) {
|
||||
case TDA18271_ANALOG:
|
||||
regs[R_MPD] &= ~0x08;
|
||||
break;
|
||||
case TDA18271_DIGITAL:
|
||||
regs[R_MPD] |= 0x08;
|
||||
break;
|
||||
}
|
||||
regs[R_MPD] = (0x7f & pd);
|
||||
|
||||
div = ((d * (freq / 1000)) << 7) / 125;
|
||||
|
||||
|
|
|
@ -579,8 +579,8 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
|
|||
#define RF3 2
|
||||
u32 rf_default[3];
|
||||
u32 rf_freq[3];
|
||||
u8 prog_cal[3];
|
||||
u8 prog_tab[3];
|
||||
s32 prog_cal[3];
|
||||
s32 prog_tab[3];
|
||||
|
||||
i = tda18271_lookup_rf_band(fe, &freq, NULL);
|
||||
|
||||
|
@ -602,32 +602,33 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
|
|||
return bcal;
|
||||
|
||||
tda18271_calc_rf_cal(fe, &rf_freq[rf]);
|
||||
prog_tab[rf] = regs[R_EB14];
|
||||
prog_tab[rf] = (s32)regs[R_EB14];
|
||||
|
||||
if (1 == bcal)
|
||||
prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
|
||||
prog_cal[rf] =
|
||||
(s32)tda18271_calibrate_rf(fe, rf_freq[rf]);
|
||||
else
|
||||
prog_cal[rf] = prog_tab[rf];
|
||||
|
||||
switch (rf) {
|
||||
case RF1:
|
||||
map[i].rf_a1 = 0;
|
||||
map[i].rf_b1 = (s32)(prog_cal[RF1] - prog_tab[RF1]);
|
||||
map[i].rf_b1 = (prog_cal[RF1] - prog_tab[RF1]);
|
||||
map[i].rf1 = rf_freq[RF1] / 1000;
|
||||
break;
|
||||
case RF2:
|
||||
dividend = (s32)(prog_cal[RF2] - prog_tab[RF2]) -
|
||||
(s32)(prog_cal[RF1] + prog_tab[RF1]);
|
||||
dividend = (prog_cal[RF2] - prog_tab[RF2] -
|
||||
prog_cal[RF1] + prog_tab[RF1]);
|
||||
divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000;
|
||||
map[i].rf_a1 = (dividend / divisor);
|
||||
map[i].rf2 = rf_freq[RF2] / 1000;
|
||||
break;
|
||||
case RF3:
|
||||
dividend = (s32)(prog_cal[RF3] - prog_tab[RF3]) -
|
||||
(s32)(prog_cal[RF2] + prog_tab[RF2]);
|
||||
dividend = (prog_cal[RF3] - prog_tab[RF3] -
|
||||
prog_cal[RF2] + prog_tab[RF2]);
|
||||
divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000;
|
||||
map[i].rf_a2 = (dividend / divisor);
|
||||
map[i].rf_b2 = (s32)(prog_cal[RF2] - prog_tab[RF2]);
|
||||
map[i].rf_b2 = (prog_cal[RF2] - prog_tab[RF2]);
|
||||
map[i].rf3 = rf_freq[RF3] / 1000;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -229,8 +229,7 @@ static struct tda18271_map tda18271c2_km[] = {
|
|||
static struct tda18271_map tda18271_rf_band[] = {
|
||||
{ .rfmax = 47900, .val = 0x00 },
|
||||
{ .rfmax = 61100, .val = 0x01 },
|
||||
/* { .rfmax = 152600, .val = 0x02 }, */
|
||||
{ .rfmax = 121200, .val = 0x02 },
|
||||
{ .rfmax = 152600, .val = 0x02 },
|
||||
{ .rfmax = 164700, .val = 0x03 },
|
||||
{ .rfmax = 203500, .val = 0x04 },
|
||||
{ .rfmax = 457800, .val = 0x05 },
|
||||
|
@ -448,7 +447,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
|
|||
{ .rfmax = 150000, .val = 0xb0 },
|
||||
{ .rfmax = 151000, .val = 0xb1 },
|
||||
{ .rfmax = 152000, .val = 0xb7 },
|
||||
{ .rfmax = 153000, .val = 0xbd },
|
||||
{ .rfmax = 152600, .val = 0xbd },
|
||||
{ .rfmax = 154000, .val = 0x20 },
|
||||
{ .rfmax = 155000, .val = 0x22 },
|
||||
{ .rfmax = 156000, .val = 0x24 },
|
||||
|
@ -459,7 +458,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
|
|||
{ .rfmax = 161000, .val = 0x2d },
|
||||
{ .rfmax = 163000, .val = 0x2e },
|
||||
{ .rfmax = 164000, .val = 0x2f },
|
||||
{ .rfmax = 165000, .val = 0x30 },
|
||||
{ .rfmax = 164700, .val = 0x30 },
|
||||
{ .rfmax = 166000, .val = 0x11 },
|
||||
{ .rfmax = 167000, .val = 0x12 },
|
||||
{ .rfmax = 168000, .val = 0x13 },
|
||||
|
@ -510,7 +509,8 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
|
|||
{ .rfmax = 236000, .val = 0x1b },
|
||||
{ .rfmax = 237000, .val = 0x1c },
|
||||
{ .rfmax = 240000, .val = 0x1d },
|
||||
{ .rfmax = 242000, .val = 0x1f },
|
||||
{ .rfmax = 242000, .val = 0x1e },
|
||||
{ .rfmax = 244000, .val = 0x1f },
|
||||
{ .rfmax = 247000, .val = 0x20 },
|
||||
{ .rfmax = 249000, .val = 0x21 },
|
||||
{ .rfmax = 252000, .val = 0x22 },
|
||||
|
@ -624,7 +624,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
|
|||
{ .rfmax = 453000, .val = 0x93 },
|
||||
{ .rfmax = 454000, .val = 0x94 },
|
||||
{ .rfmax = 456000, .val = 0x96 },
|
||||
{ .rfmax = 457000, .val = 0x98 },
|
||||
{ .rfmax = 457800, .val = 0x98 },
|
||||
{ .rfmax = 461000, .val = 0x11 },
|
||||
{ .rfmax = 468000, .val = 0x12 },
|
||||
{ .rfmax = 472000, .val = 0x13 },
|
||||
|
|
|
@ -38,7 +38,7 @@ MODULE_PARM_DESC(debug,
|
|||
DEBSTATUS);
|
||||
|
||||
#define DRIVER_VERSION "0.1"
|
||||
#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
|
||||
#define DRIVER_NAME "flexcop-pci"
|
||||
#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
|
||||
|
||||
struct flexcop_pci {
|
||||
|
|
|
@ -362,7 +362,7 @@ config DVB_USB_LME2510
|
|||
config DVB_USB_TECHNISAT_USB2
|
||||
tristate "Technisat DVB-S/S2 USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV090x if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV6110x if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Technisat USB2 DVB-S/S2 device
|
||||
|
|
|
@ -2162,7 +2162,7 @@ struct dibx000_agc_config dib7090_agc_config[2] = {
|
|||
.agc1_pt3 = 98,
|
||||
.agc1_slope1 = 0,
|
||||
.agc1_slope2 = 167,
|
||||
.agc1_pt1 = 98,
|
||||
.agc2_pt1 = 98,
|
||||
.agc2_pt2 = 255,
|
||||
.agc2_slope1 = 104,
|
||||
.agc2_slope2 = 0,
|
||||
|
@ -2440,11 +2440,11 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
|
|||
dib0700_set_i2c_speed(adap->dev, 340);
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
|
||||
|
||||
dib7090_slave_reset(adap->fe);
|
||||
|
||||
if (adap->fe == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
dib7090_slave_reset(adap->fe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -378,7 +378,6 @@ EXPORT_SYMBOL_GPL(media_entity_create_link);
|
|||
|
||||
static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
|
||||
{
|
||||
const u32 mask = MEDIA_LNK_FL_ENABLED;
|
||||
int ret;
|
||||
|
||||
/* Notify both entities. */
|
||||
|
@ -395,7 +394,7 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
|
|||
return ret;
|
||||
}
|
||||
|
||||
link->flags = (link->flags & ~mask) | (flags & mask);
|
||||
link->flags = flags;
|
||||
link->reverse->flags = link->flags;
|
||||
|
||||
return 0;
|
||||
|
@ -417,6 +416,7 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
|
|||
*/
|
||||
int __media_entity_setup_link(struct media_link *link, u32 flags)
|
||||
{
|
||||
const u32 mask = MEDIA_LNK_FL_ENABLED;
|
||||
struct media_device *mdev;
|
||||
struct media_entity *source, *sink;
|
||||
int ret = -EBUSY;
|
||||
|
@ -424,6 +424,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
|
|||
if (link == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* The non-modifiable link flags must not be modified. */
|
||||
if ((link->flags & ~mask) != (flags & ~mask))
|
||||
return -EINVAL;
|
||||
|
||||
if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
|
||||
return link->flags == flags ? 0 : -EINVAL;
|
||||
|
||||
|
|
|
@ -875,7 +875,7 @@ config MX3_VIDEO
|
|||
config VIDEO_MX3
|
||||
tristate "i.MX3x Camera Sensor Interface driver"
|
||||
depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
select MX3_VIDEO
|
||||
---help---
|
||||
This is a v4l2 driver for the i.MX3x Camera Sensor Interface
|
||||
|
|
|
@ -350,9 +350,17 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
|
|||
|
||||
/* No struct video_device, but can have buffers allocated */
|
||||
if (type == CX18_ENC_STREAM_TYPE_IDX) {
|
||||
/* If the module params didn't inhibit IDX ... */
|
||||
if (cx->stream_buffers[type] != 0) {
|
||||
cx->stream_buffers[type] = 0;
|
||||
cx18_stream_free(&cx->streams[type]);
|
||||
/*
|
||||
* Before calling cx18_stream_free(),
|
||||
* check if the IDX stream was actually set up.
|
||||
* Needed, since the cx18_probe() error path
|
||||
* exits through here as well as normal clean up
|
||||
*/
|
||||
if (cx->streams[type].buffers != 0)
|
||||
cx18_stream_free(&cx->streams[type]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ config VIDEO_CX23885
|
|||
select DVB_CX24116 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0900 if !DVB_FE_CUSTOMISE
|
||||
select DVB_DS3000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0367 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
|
||||
|
|
|
@ -298,7 +298,7 @@ static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
|
|||
static int imx074_set_bus_param(struct soc_camera_device *icd,
|
||||
unsigned long flags)
|
||||
{
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct soc_camera_ops imx074_ops = {
|
||||
|
|
|
@ -215,20 +215,21 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
|
|||
}
|
||||
|
||||
switch (xclksel) {
|
||||
case 0:
|
||||
case ISP_XCLK_A:
|
||||
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
|
||||
ISPTCTRL_CTRL_DIVA_MASK,
|
||||
divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
|
||||
dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
|
||||
currentxclk);
|
||||
break;
|
||||
case 1:
|
||||
case ISP_XCLK_B:
|
||||
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
|
||||
ISPTCTRL_CTRL_DIVB_MASK,
|
||||
divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
|
||||
dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
|
||||
currentxclk);
|
||||
break;
|
||||
case ISP_XCLK_NONE:
|
||||
default:
|
||||
omap3isp_put(isp);
|
||||
dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
|
||||
|
@ -237,13 +238,13 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
|
|||
}
|
||||
|
||||
/* Do we go from stable whatever to clock? */
|
||||
if (divisor >= 2 && isp->xclk_divisor[xclksel] < 2)
|
||||
if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
|
||||
omap3isp_get(isp);
|
||||
/* Stopping the clock. */
|
||||
else if (divisor < 2 && isp->xclk_divisor[xclksel] >= 2)
|
||||
else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
|
||||
omap3isp_put(isp);
|
||||
|
||||
isp->xclk_divisor[xclksel] = divisor;
|
||||
isp->xclk_divisor[xclksel - 1] = divisor;
|
||||
|
||||
omap3isp_put(isp);
|
||||
|
||||
|
@ -285,7 +286,8 @@ static void isp_power_settings(struct isp_device *isp, int idle)
|
|||
*/
|
||||
void omap3isp_configure_bridge(struct isp_device *isp,
|
||||
enum ccdc_input_entity input,
|
||||
const struct isp_parallel_platform_data *pdata)
|
||||
const struct isp_parallel_platform_data *pdata,
|
||||
unsigned int shift)
|
||||
{
|
||||
u32 ispctrl_val;
|
||||
|
||||
|
@ -298,9 +300,9 @@ void omap3isp_configure_bridge(struct isp_device *isp,
|
|||
switch (input) {
|
||||
case CCDC_INPUT_PARALLEL:
|
||||
ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
|
||||
ispctrl_val |= pdata->data_lane_shift << ISPCTRL_SHIFT_SHIFT;
|
||||
ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
|
||||
ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
|
||||
shift += pdata->data_lane_shift * 2;
|
||||
break;
|
||||
|
||||
case CCDC_INPUT_CSI2A:
|
||||
|
@ -319,6 +321,8 @@ void omap3isp_configure_bridge(struct isp_device *isp,
|
|||
return;
|
||||
}
|
||||
|
||||
ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
|
||||
|
||||
ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
|
||||
ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
|
||||
|
||||
|
@ -658,6 +662,8 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
|
|||
|
||||
/* Apply power change to connected non-nodes. */
|
||||
ret = isp_pipeline_pm_power(entity, change);
|
||||
if (ret < 0)
|
||||
entity->use_count -= change;
|
||||
|
||||
mutex_unlock(&entity->parent->graph_mutex);
|
||||
|
||||
|
@ -872,6 +878,9 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
|
|||
}
|
||||
}
|
||||
|
||||
if (failure < 0)
|
||||
isp->needs_reset = true;
|
||||
|
||||
return failure;
|
||||
}
|
||||
|
||||
|
@ -884,7 +893,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
|
|||
* single-shot or continuous mode.
|
||||
*
|
||||
* Return 0 if successful, or the return value of the failed video::s_stream
|
||||
* operation otherwise.
|
||||
* operation otherwise. The pipeline state is not updated when the operation
|
||||
* fails, except when stopping the pipeline.
|
||||
*/
|
||||
int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
|
||||
enum isp_pipeline_stream_state state)
|
||||
|
@ -895,7 +905,9 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
|
|||
ret = isp_pipeline_disable(pipe);
|
||||
else
|
||||
ret = isp_pipeline_enable(pipe, state);
|
||||
pipe->stream_state = state;
|
||||
|
||||
if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
|
||||
pipe->stream_state = state;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1481,6 +1493,10 @@ void omap3isp_put(struct isp_device *isp)
|
|||
if (--isp->ref_count == 0) {
|
||||
isp_disable_interrupts(isp);
|
||||
isp_save_ctx(isp);
|
||||
if (isp->needs_reset) {
|
||||
isp_reset(isp);
|
||||
isp->needs_reset = false;
|
||||
}
|
||||
isp_disable_clocks(isp);
|
||||
}
|
||||
mutex_unlock(&isp->isp_mutex);
|
||||
|
|
|
@ -132,7 +132,6 @@ struct isp_reg {
|
|||
|
||||
/**
|
||||
* struct isp_parallel_platform_data - Parallel interface platform data
|
||||
* @width: Parallel bus width in bits (8, 10, 11 or 12)
|
||||
* @data_lane_shift: Data lane shifter
|
||||
* 0 - CAMEXT[13:0] -> CAM[13:0]
|
||||
* 1 - CAMEXT[13:2] -> CAM[11:0]
|
||||
|
@ -146,7 +145,6 @@ struct isp_reg {
|
|||
* ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
|
||||
*/
|
||||
struct isp_parallel_platform_data {
|
||||
unsigned int width;
|
||||
unsigned int data_lane_shift:2;
|
||||
unsigned int clk_pol:1;
|
||||
unsigned int bridge:4;
|
||||
|
@ -262,6 +260,7 @@ struct isp_device {
|
|||
/* ISP Obj */
|
||||
spinlock_t stat_lock; /* common lock for statistic drivers */
|
||||
struct mutex isp_mutex; /* For handling ref_count field */
|
||||
bool needs_reset;
|
||||
int has_context;
|
||||
int ref_count;
|
||||
unsigned int autoidle;
|
||||
|
@ -311,11 +310,12 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
|
|||
enum isp_pipeline_stream_state state);
|
||||
void omap3isp_configure_bridge(struct isp_device *isp,
|
||||
enum ccdc_input_entity input,
|
||||
const struct isp_parallel_platform_data *pdata);
|
||||
const struct isp_parallel_platform_data *pdata,
|
||||
unsigned int shift);
|
||||
|
||||
#define ISP_XCLK_NONE -1
|
||||
#define ISP_XCLK_A 0
|
||||
#define ISP_XCLK_B 1
|
||||
#define ISP_XCLK_NONE 0
|
||||
#define ISP_XCLK_A 1
|
||||
#define ISP_XCLK_B 2
|
||||
|
||||
struct isp_device *omap3isp_get(struct isp_device *isp);
|
||||
void omap3isp_put(struct isp_device *isp);
|
||||
|
|
|
@ -43,6 +43,12 @@ __ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
|
|||
|
||||
static const unsigned int ccdc_fmts[] = {
|
||||
V4L2_MBUS_FMT_Y8_1X8,
|
||||
V4L2_MBUS_FMT_Y10_1X10,
|
||||
V4L2_MBUS_FMT_Y12_1X12,
|
||||
V4L2_MBUS_FMT_SGRBG8_1X8,
|
||||
V4L2_MBUS_FMT_SRGGB8_1X8,
|
||||
V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||
V4L2_MBUS_FMT_SGBRG8_1X8,
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10,
|
||||
V4L2_MBUS_FMT_SRGGB10_1X10,
|
||||
V4L2_MBUS_FMT_SBGGR10_1X10,
|
||||
|
@ -1110,21 +1116,38 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
|
|||
struct isp_parallel_platform_data *pdata = NULL;
|
||||
struct v4l2_subdev *sensor;
|
||||
struct v4l2_mbus_framefmt *format;
|
||||
const struct isp_format_info *fmt_info;
|
||||
struct v4l2_subdev_format fmt_src;
|
||||
unsigned int depth_out;
|
||||
unsigned int depth_in = 0;
|
||||
struct media_pad *pad;
|
||||
unsigned long flags;
|
||||
unsigned int shift;
|
||||
u32 syn_mode;
|
||||
u32 ccdc_pattern;
|
||||
|
||||
if (ccdc->input == CCDC_INPUT_PARALLEL) {
|
||||
pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
|
||||
sensor = media_entity_to_v4l2_subdev(pad->entity);
|
||||
pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
|
||||
sensor = media_entity_to_v4l2_subdev(pad->entity);
|
||||
if (ccdc->input == CCDC_INPUT_PARALLEL)
|
||||
pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
|
||||
->bus.parallel;
|
||||
|
||||
/* Compute shift value for lane shifter to configure the bridge. */
|
||||
fmt_src.pad = pad->index;
|
||||
fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
|
||||
fmt_info = omap3isp_video_format_info(fmt_src.format.code);
|
||||
depth_in = fmt_info->bpp;
|
||||
}
|
||||
|
||||
omap3isp_configure_bridge(isp, ccdc->input, pdata);
|
||||
fmt_info = omap3isp_video_format_info
|
||||
(isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
|
||||
depth_out = fmt_info->bpp;
|
||||
|
||||
ccdc->syncif.datsz = pdata ? pdata->width : 10;
|
||||
shift = depth_in - depth_out;
|
||||
omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
|
||||
|
||||
ccdc->syncif.datsz = depth_out;
|
||||
ccdc_config_sync_if(ccdc, &ccdc->syncif);
|
||||
|
||||
/* CCDC_PAD_SINK */
|
||||
|
@ -1338,7 +1361,7 @@ static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
|
|||
* @ccdc: Pointer to ISP CCDC device.
|
||||
* @event: Pointing which event trigger handler
|
||||
*
|
||||
* Return 1 when the event and stopping request combination is satisfyied,
|
||||
* Return 1 when the event and stopping request combination is satisfied,
|
||||
* zero otherwise.
|
||||
*/
|
||||
static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
|
||||
|
@ -1618,7 +1641,7 @@ static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
|
|||
|
||||
ccdc_set_outaddr(ccdc, buffer->isp_addr);
|
||||
|
||||
/* We now have a buffer queued on the output, restart the pipeline in
|
||||
/* We now have a buffer queued on the output, restart the pipeline
|
||||
* on the next CCDC interrupt if running in continuous mode (or when
|
||||
* starting the stream).
|
||||
*/
|
||||
|
|
|
@ -755,7 +755,7 @@ static struct preview_update update_attrs[] = {
|
|||
* @configs - pointer to update config structure.
|
||||
* @config - return pointer to appropriate structure field.
|
||||
* @bit - for which feature to return pointers.
|
||||
* Return size of coresponding prev_params member
|
||||
* Return size of corresponding prev_params member
|
||||
*/
|
||||
static u32
|
||||
__preview_get_ptrs(struct prev_params *params, void **param,
|
||||
|
|
|
@ -339,7 +339,7 @@ static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
|
|||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
if (ret != buf->npages) {
|
||||
buf->npages = ret;
|
||||
buf->npages = ret < 0 ? 0 : ret;
|
||||
isp_video_buffer_cleanup(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -408,8 +408,8 @@ static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf)
|
|||
* isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
|
||||
*
|
||||
* This function locates the VMAs for the buffer's userspace address and checks
|
||||
* that their flags match. The onlflag that we need to care for at the moment is
|
||||
* VM_PFNMAP.
|
||||
* that their flags match. The only flag that we need to care for at the moment
|
||||
* is VM_PFNMAP.
|
||||
*
|
||||
* The buffer vm_flags field is set to the first VMA flags.
|
||||
*
|
||||
|
|
|
@ -714,19 +714,50 @@ static void resizer_print_status(struct isp_res_device *res)
|
|||
* iw and ih are the input width and height after cropping. Those equations need
|
||||
* to be satisfied exactly for the resizer to work correctly.
|
||||
*
|
||||
* Reverting the equations, we can compute the resizing ratios with
|
||||
* The equations can't be easily reverted, as the >> 8 operation is not linear.
|
||||
* In addition, not all input sizes can be achieved for a given output size. To
|
||||
* get the highest input size lower than or equal to the requested input size,
|
||||
* we need to compute the highest resizing ratio that satisfies the following
|
||||
* inequality (taking the 4-tap mode width equation as an example)
|
||||
*
|
||||
* iw >= (32 * sph + (ow - 1) * hrsz + 16) >> 8 - 7
|
||||
*
|
||||
* (where iw is the requested input width) which can be rewritten as
|
||||
*
|
||||
* iw - 7 >= (32 * sph + (ow - 1) * hrsz + 16) >> 8
|
||||
* (iw - 7) << 8 >= 32 * sph + (ow - 1) * hrsz + 16 - b
|
||||
* ((iw - 7) << 8) + b >= 32 * sph + (ow - 1) * hrsz + 16
|
||||
*
|
||||
* where b is the value of the 8 least significant bits of the right hand side
|
||||
* expression of the last inequality. The highest resizing ratio value will be
|
||||
* achieved when b is equal to its maximum value of 255. That resizing ratio
|
||||
* value will still satisfy the original inequality, as b will disappear when
|
||||
* the expression will be shifted right by 8.
|
||||
*
|
||||
* The reverted the equations thus become
|
||||
*
|
||||
* - 8-phase, 4-tap mode
|
||||
* hrsz = ((iw - 7) * 256 - 16 - 32 * sph) / (ow - 1)
|
||||
* vrsz = ((ih - 4) * 256 - 16 - 32 * spv) / (oh - 1)
|
||||
* hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
|
||||
* vrsz = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / (oh - 1)
|
||||
* - 4-phase, 7-tap mode
|
||||
* hrsz = ((iw - 7) * 256 - 32 - 64 * sph) / (ow - 1)
|
||||
* vrsz = ((ih - 7) * 256 - 32 - 64 * spv) / (oh - 1)
|
||||
* hrsz = ((iw - 7) * 256 + 255 - 32 - 64 * sph) / (ow - 1)
|
||||
* vrsz = ((ih - 7) * 256 + 255 - 32 - 64 * spv) / (oh - 1)
|
||||
*
|
||||
* The ratios are integer values, and must be rounded down to ensure that the
|
||||
* cropped input size is not bigger than the uncropped input size. As the ratio
|
||||
* in 7-tap mode is always smaller than the ratio in 4-tap mode, we can use the
|
||||
* 7-tap mode equations to compute a ratio approximation.
|
||||
* The ratios are integer values, and are rounded down to ensure that the
|
||||
* cropped input size is not bigger than the uncropped input size.
|
||||
*
|
||||
* As the number of phases/taps, used to select the correct equations to compute
|
||||
* the ratio, depends on the ratio, we start with the 4-tap mode equations to
|
||||
* compute an approximation of the ratio, and switch to the 7-tap mode equations
|
||||
* if the approximation is higher than the ratio threshold.
|
||||
*
|
||||
* As the 7-tap mode equations will return a ratio smaller than or equal to the
|
||||
* 4-tap mode equations, the resulting ratio could become lower than or equal to
|
||||
* the ratio threshold. This 'equations loop' isn't an issue as long as the
|
||||
* correct equations are used to compute the final input size. Starting with the
|
||||
* 4-tap mode equations ensure that, in case of values resulting in a 'ratio
|
||||
* loop', the smallest of the ratio values will be used, never exceeding the
|
||||
* requested input size.
|
||||
*
|
||||
* We first clamp the output size according to the hardware capabilitie to avoid
|
||||
* auto-cropping the input more than required to satisfy the TRM equations. The
|
||||
|
@ -775,6 +806,8 @@ static void resizer_calc_ratios(struct isp_res_device *res,
|
|||
unsigned int max_width;
|
||||
unsigned int max_height;
|
||||
unsigned int width_alignment;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
|
||||
/*
|
||||
* Clamp the output height based on the hardware capabilities and
|
||||
|
@ -786,19 +819,22 @@ static void resizer_calc_ratios(struct isp_res_device *res,
|
|||
max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
|
||||
output->height = clamp(output->height, min_height, max_height);
|
||||
|
||||
ratio->vert = ((input->height - 7) * 256 - 32 - 64 * spv)
|
||||
ratio->vert = ((input->height - 4) * 256 + 255 - 16 - 32 * spv)
|
||||
/ (output->height - 1);
|
||||
if (ratio->vert > MID_RESIZE_VALUE)
|
||||
ratio->vert = ((input->height - 7) * 256 + 255 - 32 - 64 * spv)
|
||||
/ (output->height - 1);
|
||||
ratio->vert = clamp_t(unsigned int, ratio->vert,
|
||||
MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
|
||||
|
||||
if (ratio->vert <= MID_RESIZE_VALUE) {
|
||||
upscaled_height = (output->height - 1) * ratio->vert
|
||||
+ 32 * spv + 16;
|
||||
input->height = (upscaled_height >> 8) + 4;
|
||||
height = (upscaled_height >> 8) + 4;
|
||||
} else {
|
||||
upscaled_height = (output->height - 1) * ratio->vert
|
||||
+ 64 * spv + 32;
|
||||
input->height = (upscaled_height >> 8) + 7;
|
||||
height = (upscaled_height >> 8) + 7;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -854,20 +890,29 @@ static void resizer_calc_ratios(struct isp_res_device *res,
|
|||
max_width & ~(width_alignment - 1));
|
||||
output->width = ALIGN(output->width, width_alignment);
|
||||
|
||||
ratio->horz = ((input->width - 7) * 256 - 32 - 64 * sph)
|
||||
ratio->horz = ((input->width - 7) * 256 + 255 - 16 - 32 * sph)
|
||||
/ (output->width - 1);
|
||||
if (ratio->horz > MID_RESIZE_VALUE)
|
||||
ratio->horz = ((input->width - 7) * 256 + 255 - 32 - 64 * sph)
|
||||
/ (output->width - 1);
|
||||
ratio->horz = clamp_t(unsigned int, ratio->horz,
|
||||
MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
|
||||
|
||||
if (ratio->horz <= MID_RESIZE_VALUE) {
|
||||
upscaled_width = (output->width - 1) * ratio->horz
|
||||
+ 32 * sph + 16;
|
||||
input->width = (upscaled_width >> 8) + 7;
|
||||
width = (upscaled_width >> 8) + 7;
|
||||
} else {
|
||||
upscaled_width = (output->width - 1) * ratio->horz
|
||||
+ 64 * sph + 32;
|
||||
input->width = (upscaled_width >> 8) + 7;
|
||||
width = (upscaled_width >> 8) + 7;
|
||||
}
|
||||
|
||||
/* Center the new crop rectangle. */
|
||||
input->left += (input->width - width) / 2;
|
||||
input->top += (input->height - height) / 2;
|
||||
input->width = width;
|
||||
input->height = height;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -131,9 +131,9 @@ struct ispstat {
|
|||
struct ispstat_generic_config {
|
||||
/*
|
||||
* Fields must be in the same order as in:
|
||||
* - isph3a_aewb_config
|
||||
* - isph3a_af_config
|
||||
* - isphist_config
|
||||
* - omap3isp_h3a_aewb_config
|
||||
* - omap3isp_h3a_af_config
|
||||
* - omap3isp_hist_config
|
||||
*/
|
||||
u32 buf_size;
|
||||
u16 config_counter;
|
||||
|
|
|
@ -47,29 +47,59 @@
|
|||
|
||||
static struct isp_format_info formats[] = {
|
||||
{ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
|
||||
V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, },
|
||||
V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
|
||||
V4L2_PIX_FMT_GREY, 8, },
|
||||
{ V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
|
||||
V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
|
||||
V4L2_PIX_FMT_Y10, 10, },
|
||||
{ V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
|
||||
V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
|
||||
V4L2_PIX_FMT_Y12, 12, },
|
||||
{ V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||
V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||
V4L2_PIX_FMT_SBGGR8, 8, },
|
||||
{ V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
|
||||
V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
|
||||
V4L2_PIX_FMT_SGBRG8, 8, },
|
||||
{ V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
|
||||
V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
|
||||
V4L2_PIX_FMT_SGRBG8, 8, },
|
||||
{ V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
|
||||
V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
|
||||
V4L2_PIX_FMT_SRGGB8, 8, },
|
||||
{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10, 0,
|
||||
V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
|
||||
{ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
|
||||
V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, },
|
||||
V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||
V4L2_PIX_FMT_SBGGR10, 10, },
|
||||
{ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
|
||||
V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, },
|
||||
V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
|
||||
V4L2_PIX_FMT_SGBRG10, 10, },
|
||||
{ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, },
|
||||
V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
|
||||
V4L2_PIX_FMT_SGRBG10, 10, },
|
||||
{ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
|
||||
V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, },
|
||||
V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
|
||||
V4L2_PIX_FMT_SRGGB10, 10, },
|
||||
{ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
|
||||
V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, },
|
||||
V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
|
||||
V4L2_PIX_FMT_SBGGR12, 12, },
|
||||
{ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
|
||||
V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, },
|
||||
V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
|
||||
V4L2_PIX_FMT_SGBRG12, 12, },
|
||||
{ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
|
||||
V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, },
|
||||
V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
|
||||
V4L2_PIX_FMT_SGRBG12, 12, },
|
||||
{ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
|
||||
V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, },
|
||||
V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
|
||||
V4L2_PIX_FMT_SRGGB12, 12, },
|
||||
{ V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
|
||||
V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, },
|
||||
V4L2_MBUS_FMT_UYVY8_1X16, 0,
|
||||
V4L2_PIX_FMT_UYVY, 16, },
|
||||
{ V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
|
||||
V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, },
|
||||
V4L2_MBUS_FMT_YUYV8_1X16, 0,
|
||||
V4L2_PIX_FMT_YUYV, 16, },
|
||||
};
|
||||
|
||||
const struct isp_format_info *
|
||||
|
@ -85,6 +115,37 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide whether desired output pixel code can be obtained with
|
||||
* the lane shifter by shifting the input pixel code.
|
||||
* @in: input pixelcode to shifter
|
||||
* @out: output pixelcode from shifter
|
||||
* @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
|
||||
*
|
||||
* return true if the combination is possible
|
||||
* return false otherwise
|
||||
*/
|
||||
static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
|
||||
enum v4l2_mbus_pixelcode out,
|
||||
unsigned int additional_shift)
|
||||
{
|
||||
const struct isp_format_info *in_info, *out_info;
|
||||
|
||||
if (in == out)
|
||||
return true;
|
||||
|
||||
in_info = omap3isp_video_format_info(in);
|
||||
out_info = omap3isp_video_format_info(out);
|
||||
|
||||
if ((in_info->flavor == 0) || (out_info->flavor == 0))
|
||||
return false;
|
||||
|
||||
if (in_info->flavor != out_info->flavor)
|
||||
return false;
|
||||
|
||||
return in_info->bpp - out_info->bpp + additional_shift <= 6;
|
||||
}
|
||||
|
||||
/*
|
||||
* isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
|
||||
* @video: ISP video instance
|
||||
|
@ -235,6 +296,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
|
|||
return -EPIPE;
|
||||
|
||||
while (1) {
|
||||
unsigned int shifter_link;
|
||||
/* Retrieve the sink format */
|
||||
pad = &subdev->entity.pads[0];
|
||||
if (!(pad->flags & MEDIA_PAD_FL_SINK))
|
||||
|
@ -263,6 +325,10 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/* If sink pad is on CCDC, the link has the lane shifter
|
||||
* in the middle of it. */
|
||||
shifter_link = subdev == &isp->isp_ccdc.subdev;
|
||||
|
||||
/* Retrieve the source format */
|
||||
pad = media_entity_remote_source(pad);
|
||||
if (pad == NULL ||
|
||||
|
@ -278,10 +344,24 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
|
|||
return -EPIPE;
|
||||
|
||||
/* Check if the two ends match */
|
||||
if (fmt_source.format.code != fmt_sink.format.code ||
|
||||
fmt_source.format.width != fmt_sink.format.width ||
|
||||
if (fmt_source.format.width != fmt_sink.format.width ||
|
||||
fmt_source.format.height != fmt_sink.format.height)
|
||||
return -EPIPE;
|
||||
|
||||
if (shifter_link) {
|
||||
unsigned int parallel_shift = 0;
|
||||
if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
|
||||
struct isp_parallel_platform_data *pdata =
|
||||
&((struct isp_v4l2_subdevs_group *)
|
||||
subdev->host_priv)->bus.parallel;
|
||||
parallel_shift = pdata->data_lane_shift * 2;
|
||||
}
|
||||
if (!isp_video_is_shiftable(fmt_source.format.code,
|
||||
fmt_sink.format.code,
|
||||
parallel_shift))
|
||||
return -EPIPE;
|
||||
} else if (fmt_source.format.code != fmt_sink.format.code)
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -49,6 +49,8 @@ struct v4l2_pix_format;
|
|||
* bits. Identical to @code if the format is 10 bits wide or less.
|
||||
* @uncompressed: V4L2 media bus format code for the corresponding uncompressed
|
||||
* format. Identical to @code if the format is not DPCM compressed.
|
||||
* @flavor: V4L2 media bus format code for the same pixel layout but
|
||||
* shifted to be 8 bits per pixel. =0 if format is not shiftable.
|
||||
* @pixelformat: V4L2 pixel format FCC identifier
|
||||
* @bpp: Bits per pixel
|
||||
*/
|
||||
|
@ -56,6 +58,7 @@ struct isp_format_info {
|
|||
enum v4l2_mbus_pixelcode code;
|
||||
enum v4l2_mbus_pixelcode truncated;
|
||||
enum v4l2_mbus_pixelcode uncompressed;
|
||||
enum v4l2_mbus_pixelcode flavor;
|
||||
u32 pixelformat;
|
||||
unsigned int bpp;
|
||||
};
|
||||
|
|
|
@ -527,7 +527,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (vb2_is_streaming(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
|
||||
if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
|
||||
return -EBUSY;
|
||||
|
||||
frame = &ctx->d_frame;
|
||||
|
@ -539,8 +539,10 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < frame->fmt->colplanes; i++)
|
||||
frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
|
||||
for (i = 0; i < frame->fmt->colplanes; i++) {
|
||||
frame->payload[i] =
|
||||
(pix->width * pix->height * frame->fmt->depth[i]) >> 3;
|
||||
}
|
||||
|
||||
/* Output DMA frame pixel size and offsets. */
|
||||
frame->f_width = pix->plane_fmt[0].bytesperline * 8
|
||||
|
|
|
@ -361,10 +361,20 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
|
|||
{
|
||||
struct fimc_vid_cap *cap = &fimc->vid_cap;
|
||||
struct fimc_vid_buffer *v_buf;
|
||||
struct timeval *tv;
|
||||
struct timespec ts;
|
||||
|
||||
if (!list_empty(&cap->active_buf_q) &&
|
||||
test_bit(ST_CAPT_RUN, &fimc->state)) {
|
||||
ktime_get_real_ts(&ts);
|
||||
|
||||
v_buf = active_queue_pop(cap);
|
||||
|
||||
tv = &v_buf->vb.v4l2_buf.timestamp;
|
||||
tv->tv_sec = ts.tv_sec;
|
||||
tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
|
||||
v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
|
||||
|
||||
vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
|
||||
}
|
||||
|
||||
|
@ -758,7 +768,7 @@ static void fimc_unlock(struct vb2_queue *vq)
|
|||
mutex_unlock(&ctx->fimc_dev->lock);
|
||||
}
|
||||
|
||||
struct vb2_ops fimc_qops = {
|
||||
static struct vb2_ops fimc_qops = {
|
||||
.queue_setup = fimc_queue_setup,
|
||||
.buf_prepare = fimc_buf_prepare,
|
||||
.buf_queue = fimc_buf_queue,
|
||||
|
@ -927,23 +937,23 @@ int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
|
|||
pix->num_planes = fmt->memplanes;
|
||||
pix->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
|
||||
|
||||
for (i = 0; i < pix->num_planes; ++i) {
|
||||
int bpl = pix->plane_fmt[i].bytesperline;
|
||||
u32 bpl = pix->plane_fmt[i].bytesperline;
|
||||
u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
|
||||
|
||||
dbg("[%d] bpl: %d, depth: %d, w: %d, h: %d",
|
||||
i, bpl, fmt->depth[i], pix->width, pix->height);
|
||||
if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
|
||||
bpl = pix->width; /* Planar */
|
||||
|
||||
if (!bpl || (bpl * 8 / fmt->depth[i]) > pix->width)
|
||||
bpl = (pix->width * fmt->depth[0]) >> 3;
|
||||
if (fmt->colplanes == 1 && /* Packed */
|
||||
(bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
|
||||
bpl = (pix->width * fmt->depth[0]) / 8;
|
||||
|
||||
if (!pix->plane_fmt[i].sizeimage)
|
||||
pix->plane_fmt[i].sizeimage = pix->height * bpl;
|
||||
if (i == 0) /* Same bytesperline for each plane. */
|
||||
mod_x = bpl;
|
||||
|
||||
pix->plane_fmt[i].bytesperline = bpl;
|
||||
|
||||
dbg("[%d]: bpl: %d, sizeimage: %d",
|
||||
i, pix->plane_fmt[i].bytesperline,
|
||||
pix->plane_fmt[i].sizeimage);
|
||||
pix->plane_fmt[i].bytesperline = mod_x;
|
||||
*sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -965,7 +975,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
|
|||
|
||||
vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
|
||||
|
||||
if (vb2_is_streaming(vq)) {
|
||||
if (vb2_is_busy(vq)) {
|
||||
v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -985,8 +995,10 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
|
|||
if (!frame->fmt)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < frame->fmt->colplanes; i++)
|
||||
frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
|
||||
for (i = 0; i < frame->fmt->colplanes; i++) {
|
||||
frame->payload[i] =
|
||||
(pix->width * pix->height * frame->fmt->depth[i]) / 8;
|
||||
}
|
||||
|
||||
frame->f_width = pix->plane_fmt[0].bytesperline * 8 /
|
||||
frame->fmt->depth[0];
|
||||
|
@ -1750,7 +1762,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Image pixel limits, similar across several FIMC HW revisions. */
|
||||
static struct fimc_pix_limit s5p_pix_limit[3] = {
|
||||
static struct fimc_pix_limit s5p_pix_limit[4] = {
|
||||
[0] = {
|
||||
.scaler_en_w = 3264,
|
||||
.scaler_dis_w = 8192,
|
||||
|
@ -1775,6 +1787,14 @@ static struct fimc_pix_limit s5p_pix_limit[3] = {
|
|||
.out_rot_en_w = 1280,
|
||||
.out_rot_dis_w = 1920,
|
||||
},
|
||||
[3] = {
|
||||
.scaler_en_w = 1920,
|
||||
.scaler_dis_w = 8192,
|
||||
.in_rot_en_h = 1366,
|
||||
.in_rot_dis_w = 8192,
|
||||
.out_rot_en_w = 1366,
|
||||
.out_rot_dis_w = 1920,
|
||||
},
|
||||
};
|
||||
|
||||
static struct samsung_fimc_variant fimc0_variant_s5p = {
|
||||
|
@ -1827,7 +1847,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
|
|||
.pix_limit = &s5p_pix_limit[2],
|
||||
};
|
||||
|
||||
static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
|
||||
static struct samsung_fimc_variant fimc0_variant_exynos4 = {
|
||||
.pix_hoff = 1,
|
||||
.has_inp_rot = 1,
|
||||
.has_out_rot = 1,
|
||||
|
@ -1840,7 +1860,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
|
|||
.pix_limit = &s5p_pix_limit[1],
|
||||
};
|
||||
|
||||
static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
|
||||
static struct samsung_fimc_variant fimc2_variant_exynos4 = {
|
||||
.pix_hoff = 1,
|
||||
.has_cistatus2 = 1,
|
||||
.has_mainscaler_ext = 1,
|
||||
|
@ -1848,7 +1868,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
|
|||
.min_out_pixsize = 16,
|
||||
.hor_offs_align = 1,
|
||||
.out_buf_count = 32,
|
||||
.pix_limit = &s5p_pix_limit[2],
|
||||
.pix_limit = &s5p_pix_limit[3],
|
||||
};
|
||||
|
||||
/* S5PC100 */
|
||||
|
@ -1874,12 +1894,12 @@ static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
|
|||
};
|
||||
|
||||
/* S5PV310, S5PC210 */
|
||||
static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
|
||||
static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
|
||||
.variant = {
|
||||
[0] = &fimc0_variant_s5pv310,
|
||||
[1] = &fimc0_variant_s5pv310,
|
||||
[2] = &fimc0_variant_s5pv310,
|
||||
[3] = &fimc2_variant_s5pv310,
|
||||
[0] = &fimc0_variant_exynos4,
|
||||
[1] = &fimc0_variant_exynos4,
|
||||
[2] = &fimc0_variant_exynos4,
|
||||
[3] = &fimc2_variant_exynos4,
|
||||
},
|
||||
.num_entities = 4,
|
||||
.lclk_frequency = 166000000UL,
|
||||
|
@ -1893,8 +1913,8 @@ static struct platform_device_id fimc_driver_ids[] = {
|
|||
.name = "s5pv210-fimc",
|
||||
.driver_data = (unsigned long)&fimc_drvdata_s5pv210,
|
||||
}, {
|
||||
.name = "s5pv310-fimc",
|
||||
.driver_data = (unsigned long)&fimc_drvdata_s5pv310,
|
||||
.name = "exynos4-fimc",
|
||||
.driver_data = (unsigned long)&fimc_drvdata_exynos4,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
|
|
@ -922,7 +922,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
|
|||
/* Try 2560x1920, 1280x960, 640x480, 320x240 */
|
||||
mf.width = 2560 >> shift;
|
||||
mf.height = 1920 >> shift;
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
|
||||
s_mbus_fmt, &mf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -1224,7 +1224,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
|
|||
struct v4l2_cropcap cap;
|
||||
int ret;
|
||||
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
|
||||
s_mbus_fmt, mf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -1254,7 +1254,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
|
|||
tmp_h = min(2 * tmp_h, max_height);
|
||||
mf->width = tmp_w;
|
||||
mf->height = tmp_h;
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
|
||||
s_mbus_fmt, mf);
|
||||
dev_geo(dev, "Camera scaled to %ux%u\n",
|
||||
mf->width, mf->height);
|
||||
|
@ -1658,7 +1658,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
|
|||
mf.code = xlate->code;
|
||||
mf.colorspace = pix->colorspace;
|
||||
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, try_mbus_fmt, &mf);
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1682,7 +1682,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
|
|||
*/
|
||||
mf.width = 2560;
|
||||
mf.height = 1920;
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
|
||||
ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
|
||||
try_mbus_fmt, &mf);
|
||||
if (ret < 0) {
|
||||
/* Shouldn't actually happen... */
|
||||
|
|
|
@ -38,6 +38,8 @@ struct sh_csi2 {
|
|||
void __iomem *base;
|
||||
struct platform_device *pdev;
|
||||
struct sh_csi2_client_config *client;
|
||||
unsigned long (*query_bus_param)(struct soc_camera_device *);
|
||||
int (*set_bus_param)(struct soc_camera_device *, unsigned long);
|
||||
};
|
||||
|
||||
static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
|
||||
|
@ -208,6 +210,7 @@ static int sh_csi2_notify(struct notifier_block *nb,
|
|||
case BUS_NOTIFY_BOUND_DRIVER:
|
||||
snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s",
|
||||
dev_name(v4l2_dev->dev), ".mipi-csi");
|
||||
priv->subdev.grp_id = (long)icd;
|
||||
ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev);
|
||||
dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
|
||||
if (ret < 0)
|
||||
|
@ -215,6 +218,8 @@ static int sh_csi2_notify(struct notifier_block *nb,
|
|||
|
||||
priv->client = pdata->clients + i;
|
||||
|
||||
priv->set_bus_param = icd->ops->set_bus_param;
|
||||
priv->query_bus_param = icd->ops->query_bus_param;
|
||||
icd->ops->set_bus_param = sh_csi2_set_bus_param;
|
||||
icd->ops->query_bus_param = sh_csi2_query_bus_param;
|
||||
|
||||
|
@ -226,8 +231,10 @@ static int sh_csi2_notify(struct notifier_block *nb,
|
|||
priv->client = NULL;
|
||||
|
||||
/* Driver is about to be unbound */
|
||||
icd->ops->set_bus_param = NULL;
|
||||
icd->ops->query_bus_param = NULL;
|
||||
icd->ops->set_bus_param = priv->set_bus_param;
|
||||
icd->ops->query_bus_param = priv->query_bus_param;
|
||||
priv->set_bus_param = NULL;
|
||||
priv->query_bus_param = NULL;
|
||||
|
||||
v4l2_device_unregister_subdev(&priv->subdev);
|
||||
|
||||
|
|
|
@ -996,10 +996,11 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd)
|
|||
{
|
||||
struct i2c_client *client =
|
||||
to_i2c_client(to_soc_camera_control(icd));
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
dev_set_drvdata(&icd->dev, NULL);
|
||||
v4l2_device_unregister_subdev(i2c_get_clientdata(client));
|
||||
i2c_unregister_device(client);
|
||||
i2c_put_adapter(client->adapter);
|
||||
i2c_put_adapter(adap);
|
||||
}
|
||||
#else
|
||||
#define soc_camera_init_i2c(icd, icl) (-ENODEV)
|
||||
|
@ -1071,6 +1072,9 @@ static int soc_camera_probe(struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
sd = soc_camera_to_subdev(icd);
|
||||
sd->grp_id = (long)icd;
|
||||
|
||||
/* At this point client .probe() should have run already */
|
||||
ret = soc_camera_init_user_formats(icd);
|
||||
if (ret < 0)
|
||||
|
@ -1092,7 +1096,6 @@ static int soc_camera_probe(struct device *dev)
|
|||
goto evidstart;
|
||||
|
||||
/* Try to improve our guess of a reasonable window format */
|
||||
sd = soc_camera_to_subdev(icd);
|
||||
if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
|
||||
icd->user_width = mf.width;
|
||||
icd->user_height = mf.height;
|
||||
|
|
|
@ -389,7 +389,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
|
|||
video_get(vdev);
|
||||
mutex_unlock(&videodev_lock);
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV) {
|
||||
entity = media_entity_get(&vdev->entity);
|
||||
if (!entity) {
|
||||
ret = -EBUSY;
|
||||
|
@ -415,7 +416,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
|
|||
/* decrease the refcount in case of an error */
|
||||
if (ret) {
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_entity_put(entity);
|
||||
#endif
|
||||
video_put(vdev);
|
||||
|
@ -437,7 +439,8 @@ static int v4l2_release(struct inode *inode, struct file *filp)
|
|||
mutex_unlock(vdev->lock);
|
||||
}
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_entity_put(&vdev->entity);
|
||||
#endif
|
||||
/* decrease the refcount unconditionally since the release()
|
||||
|
@ -686,7 +689,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
|
|||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
/* Part 5: Register the entity. */
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV) {
|
||||
vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
|
||||
vdev->entity.name = vdev->name;
|
||||
vdev->entity.v4l.major = VIDEO_MAJOR;
|
||||
|
@ -733,7 +737,8 @@ void video_unregister_device(struct video_device *vdev)
|
|||
return;
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_device_unregister_entity(&vdev->entity);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ module_param(debug, int, 0644);
|
|||
#define call_qop(q, op, args...) \
|
||||
(((q)->ops->op) ? ((q)->ops->op(args)) : 0)
|
||||
|
||||
#define V4L2_BUFFER_STATE_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
|
||||
V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)
|
||||
|
||||
/**
|
||||
* __vb2_buf_mem_alloc() - allocate video memory for the given buffer
|
||||
*/
|
||||
|
@ -51,7 +54,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
|
|||
for (plane = 0; plane < vb->num_planes; ++plane) {
|
||||
mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
|
||||
plane_sizes[plane]);
|
||||
if (!mem_priv)
|
||||
if (IS_ERR_OR_NULL(mem_priv))
|
||||
goto free;
|
||||
|
||||
/* Associate allocator private data with this plane */
|
||||
|
@ -284,7 +287,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
|
|||
struct vb2_queue *q = vb->vb2_queue;
|
||||
int ret = 0;
|
||||
|
||||
/* Copy back data such as timestamp, input, etc. */
|
||||
/* Copy back data such as timestamp, flags, input, etc. */
|
||||
memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
|
||||
b->input = vb->v4l2_buf.input;
|
||||
b->reserved = vb->v4l2_buf.reserved;
|
||||
|
@ -313,7 +316,10 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
|
|||
b->m.userptr = vb->v4l2_planes[0].m.userptr;
|
||||
}
|
||||
|
||||
b->flags = 0;
|
||||
/*
|
||||
* Clear any buffer state related flags.
|
||||
*/
|
||||
b->flags &= ~V4L2_BUFFER_STATE_FLAGS;
|
||||
|
||||
switch (vb->state) {
|
||||
case VB2_BUF_STATE_QUEUED:
|
||||
|
@ -519,6 +525,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
|
|||
num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
|
||||
memset(plane_sizes, 0, sizeof(plane_sizes));
|
||||
memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
|
||||
q->memory = req->memory;
|
||||
|
||||
/*
|
||||
* Ask the driver how many buffers and planes per buffer it requires.
|
||||
|
@ -560,8 +567,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
|
|||
ret = num_buffers;
|
||||
}
|
||||
|
||||
q->memory = req->memory;
|
||||
|
||||
/*
|
||||
* Return the number of successfully allocated buffers
|
||||
* to the userspace.
|
||||
|
@ -715,6 +720,8 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
|
|||
|
||||
vb->v4l2_buf.field = b->field;
|
||||
vb->v4l2_buf.timestamp = b->timestamp;
|
||||
vb->v4l2_buf.input = b->input;
|
||||
vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
|
|||
GFP_KERNEL);
|
||||
if (!buf->vaddr) {
|
||||
dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
|
||||
buf->size);
|
||||
size);
|
||||
kfree(buf);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ enum v4l2_mbus_pixelcode {
|
|||
V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
|
||||
V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
|
||||
|
||||
/* YUV (including grey) - next is 0x2013 */
|
||||
/* YUV (including grey) - next is 0x2014 */
|
||||
V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
|
||||
V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
|
||||
V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
|
||||
|
@ -60,6 +60,7 @@ enum v4l2_mbus_pixelcode {
|
|||
V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
|
||||
V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
|
||||
V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
|
||||
V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
|
||||
V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
|
||||
V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
|
||||
V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
|
||||
|
@ -67,9 +68,11 @@ enum v4l2_mbus_pixelcode {
|
|||
V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
|
||||
V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
|
||||
|
||||
/* Bayer - next is 0x3013 */
|
||||
/* Bayer - next is 0x3015 */
|
||||
V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
|
||||
V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
|
||||
V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
|
||||
V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
|
||||
V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
|
||||
V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
|
||||
V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
|
||||
|
|
|
@ -308,6 +308,7 @@ struct v4l2_pix_format {
|
|||
#define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */
|
||||
#define V4L2_PIX_FMT_Y6 v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */
|
||||
#define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */
|
||||
#define V4L2_PIX_FMT_Y12 v4l2_fourcc('Y', '1', '2', ' ') /* 12 Greyscale */
|
||||
#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */
|
||||
|
||||
/* Palette formats */
|
||||
|
|
|
@ -163,7 +163,7 @@ v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
|
|||
({ \
|
||||
struct v4l2_subdev *__sd; \
|
||||
__v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, cond, o, \
|
||||
f, args...); \
|
||||
f , ##args); \
|
||||
})
|
||||
|
||||
/* Call the specified callback for all subdevs matching grp_id (if 0, then
|
||||
|
|
Loading…
Reference in a new issue