media updates for v5.11-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAl/XHngACgkQCF8+vY7k
 4RXHjg/8CVAkeLzVHFJ8odrt/tABXd5UxFE8RvqDnrb9SRvtx1tyLmcRb/WXoAhw
 Eg0MM+o5qYN8t7uP3x16yOxzsm3ix2Z+imRiIWBLSju14BTPSD7kLp+W+AaY6kT5
 cudI/907vqIb7uEZvG7jF7jM6BJfz58Du8dnmhCgehWTBguUOChc0lBxjuTG/KGZ
 Cueiq+LgvxKeZk9GvN4H6xeMPsn/ZEB5VSe/Knp95iCA6kEFq56DC0oYCUFzi2ao
 5sX5UsX9xpertFXna/tZBTo34RIofpPcctNd98La36oIV4XIVDp0FMpKCpmaDcHM
 wCMmK/K7sGRLqS6pmPZvfA6V1uIITQbYLz4z3WO9k0rJb3LgD9ied0XmHfcgNP8P
 NxTPm4jYTk6ELc/bgB/2k1AXrOm6kWItiITKZThcuCBffoLOrRcYgsVdP+ieSeb5
 8XkhjH5jADtB2HdSNvkX9CikJMB3XzaFjqLzcaFgwDqTgw1voh2ardSp5xuZuiEJ
 fw3QEpnBYbN5XFXlkwJY7VA94Dt93OQX5pfT2fUAh6MJt+SzmW17Tup+6LsfvzL5
 yJcZ18rjyo5rr0kIfBl7FLZ7nrM9PA4erayJ2gZwCUxP9mF+URW+/UI/ytL1cOIu
 iFqzj7KRD2nwfySd5UgOkD1yViXb6M4dLf5E/t5VbyU3qIHUpwM=
 =mi60
 -----END PGP SIGNATURE-----

Merge tag 'media/v5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:

 - some rework at the uAPI pixel format docs

 - the smiapp driver has started to gain support for MIPI CSS camera
   sensors and was renamed

 - two new sensor drivers: ov02a10 and ov9734

 - Meson gained a driver for the 2D acceleration unit

 - Rockchip rkisp1 driver was promoted from staging

 - Cedrus driver gained support for VP8

 - two new remote controller keymaps were added

 - the usual set of fixes cleanups and driver improvements

* tag 'media/v5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (447 commits)
  media: ccs: Add support for obtaining C-PHY configuration from firmware
  media: ccs-pll: Print pixel rates
  media: ccs: Print written register values
  media: ccs: Add support for DDR OP SYS and OP PIX clocks
  media: ccs-pll: Add support for DDR OP system and pixel clocks
  media: ccs: Dual PLL support
  media: ccs-pll: Add trivial dual PLL support
  media: ccs-pll: Separate VT divisor limit calculation from the rest
  media: ccs-pll: Fix VT post-PLL divisor calculation
  media: ccs-pll: Make VT divisors 16-bit
  media: ccs-pll: Rework bounds checks
  media: ccs-pll: Print relevant information on PLL tree
  media: ccs-pll: Better separate OP and VT sub-tree calculation
  media: ccs-pll: Check for derating and overrating, support non-derating sensors
  media: ccs-pll: Split off VT subtree calculation
  media: ccs-pll: Add C-PHY support
  media: ccs-pll: Add sanity checks
  media: ccs-pll: Add support flexible OP PLL pixel clock divider
  media: ccs-pll: Support two cycles per pixel on OP domain
  media: ccs-pll: Add support for extended input PLL clock divider
  ...
This commit is contained in:
Linus Torvalds 2020-12-14 11:47:37 -08:00
commit fab0fca1da
408 changed files with 24047 additions and 14030 deletions

View file

@ -132,3 +132,16 @@ used to obtain device's power state after the power state transition:
The function returns a non-zero value if it succeeded getting the power count or
runtime PM was disabled, in either of which cases the driver may proceed to
access the device.
Controls
--------
For camera sensors that are connected to a bus where transmitter and receiver
require common configuration set by drivers, such as CSI-2 or parallel (BT.601
or BT.656) bus, the ``V4L2_CID_LINK_FREQ`` control is mandatory on transmitter
drivers. Receiver drivers can use the ``V4L2_CID_LINK_FREQ`` to query the
frequency used on the bus.
The transmitter drivers should also implement ``V4L2_CID_PIXEL_RATE`` control in
order to tell the maximum pixel rate to the receiver. This is required on raw
camera sensors.

View file

@ -143,7 +143,7 @@ To enable/disable the 'monitor all' mode::
int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
If enabled, then the adapter should be put in a mode to also monitor messages
that not for us. Not all hardware supports this and this function is only
that are not for us. Not all hardware supports this and this function is only
called if the CEC_CAP_MONITOR_ALL capability is set. This callback is optional
(some hardware may always be in 'monitor all' mode).
@ -335,7 +335,7 @@ So this must work:
$ cat einj.txt >error-inj
The first callback is called when this file is read and it should show the
the current error injection state::
current error injection state::
int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);

View file

@ -28,10 +28,9 @@ interface elements must be present on the sub-device represents the
CSI-2 transmitter.
The V4L2_CID_LINK_FREQ control is used to tell the receiver driver the
frequency (and not the symbol rate) of the link. The
V4L2_CID_PIXEL_RATE is may be used by the receiver to obtain the pixel
rate the transmitter uses. The
:c:type:`v4l2_subdev_video_ops`->s_stream() callback provides an
frequency (and not the symbol rate) of the link. The V4L2_CID_PIXEL_RATE
control may be used by the receiver to obtain the pixel rate the transmitter
uses. The :c:type:`v4l2_subdev_video_ops`->s_stream() callback provides an
ability to start and stop the stream.
The value of the V4L2_CID_PIXEL_RATE is calculated as follows::

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,82 @@
.. SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
.. include:: <isonum.txt>
MIPI CCS camera sensor driver
=============================
The MIPI CCS camera sensor driver is a generic driver for `MIPI CCS
<https://www.mipi.org/specifications/camera-command-set>`_ compliant
camera sensors. It exposes three sub-devices representing the pixel array,
the binner and the scaler.
As the capabilities of individual devices vary, the driver exposes
interfaces based on the capabilities that exist in hardware.
Pixel Array sub-device
----------------------
The pixel array sub-device represents the camera sensor's pixel matrix, as well
as analogue crop functionality present in many compliant devices. The analogue
crop is configured using the ``V4L2_SEL_TGT_CROP`` on the source pad (0) of the
entity. The size of the pixel matrix can be obtained by getting the
``V4L2_SEL_TGT_NATIVE_SIZE`` target.
Binner
------
The binner sub-device represents the binning functionality on the sensor. For
that purpose, selection target ``V4L2_SEL_TGT_COMPOSE`` is supported on the
sink pad (0).
Additionally, if a device has no scaler or digital crop functionality, the
source pad (1) expses another digital crop selection rectangle that can only
crop at the end of the lines and frames.
Scaler
------
The scaler sub-device represents the digital crop and scaling functionality of
the sensor. The V4L2 selection target ``V4L2_SEL_TGT_CROP`` is used to
configure the digital crop on the sink pad (0) when digital crop is supported.
Scaling is configured using selection target ``V4L2_SEL_TGT_COMPOSE`` on the
sink pad (0) as well.
Additionally, if the scaler sub-device exists, its source pad (1) exposes
another digital crop selection rectangle that can only crop at the end of the
lines and frames.
Digital and analogue crop
-------------------------
Digital crop functionality is referred to as cropping that effectively works by
dropping some data on the floor. Analogue crop, on the other hand, means that
the cropped information is never retrieved. In case of camera sensors, the
analogue data is never read from the pixel matrix that are outside the
configured selection rectangle that designates crop. The difference has an
effect in device timing and likely also in power consumption.
Register definition generator
-----------------------------
The ccs-regs.asc file contains MIPI CCS register definitions that are used
to produce C source code files for definitions that can be better used by
programs written in C language. As there are many dependencies between the
produced files, please do not modify them manually as it's error-prone and
in vain, but instead change the script producing them.
Usage
~~~~~
Conventionally the script is called this way to update the CCS driver
definitions:
.. code-block:: none
$ Documentation/driver-api/media/drivers/ccs/mk-ccs-regs -k \
-e drivers/media/i2c/ccs/ccs-regs.h \
-L drivers/media/i2c/ccs/ccs-limits.h \
-l drivers/media/i2c/ccs/ccs-limits.c \
-c Documentation/driver-api/media/drivers/ccs/ccs-regs.asc
**Copyright** |copy| 2020 Intel Corporation

View file

@ -0,0 +1,433 @@
#!/usr/bin/perl -w
# SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
# Copyright (C) 2019--2020 Intel Corporation
use Getopt::Long qw(:config no_ignore_case);
use File::Basename;
my $ccsregs = "ccs-regs.asc";
my $header;
my $regarray;
my $limitc;
my $limith;
my $kernel;
my $help;
GetOptions("ccsregs|c=s" => \$ccsregs,
"header|e=s" => \$header,
"regarray|r=s" => \$regarray,
"limitc|l=s" => \$limitc,
"limith|L=s" => \$limith,
"kernel|k" => \$kernel,
"help|h" => \$help) or die "can't parse options";
$help = 1 if ! defined $header || ! defined $limitc || ! defined $limith;
if (defined $help) {
print <<EOH
$0 - Create CCS register definitions for C
usage: $0 -c ccs-regs.asc -e header -r regarray -l limit-c -L limit-header [-k]
-c ccs register file
-e header file name
-r register description array file name
-l limit and capability array file name
-L limit and capability header file name
-k generate files for kernel space consumption
EOH
;
exit 0;
}
my $lh_hdr = ! defined $kernel
? '#include "ccs-os.h"' . "\n"
: "#include <linux/bits.h>\n#include <linux/types.h>\n";
my $uint32_t = ! defined $kernel ? 'uint32_t' : 'u32';
my $uint16_t = ! defined $kernel ? 'uint16_t' : 'u16';
open(my $R, "< $ccsregs") or die "can't open $ccsregs";
open(my $H, "> $header") or die "can't open $header";
my $A;
if (defined $regarray) {
open($A, "> $regarray") or die "can't open $regarray";
}
open(my $LC, "> $limitc") or die "can't open $limitc";
open(my $LH, "> $limith") or die "can't open $limith";
my %this;
sub is_limit_reg($) {
my $addr = hex $_[0];
return 0 if $addr < 0x40; # weed out status registers
return 0 if $addr >= 0x100 && $addr < 0xfff; # weed out configuration registers
return 1;
}
my $uc_header = basename uc $header;
$uc_header =~ s/[^A-Z0-9]/_/g;
my $copyright = "/* Copyright (C) 2019--2020 Intel Corporation */\n";
my $license = "SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause";
for my $fh ($A, $LC) {
print $fh "// $license\n$copyright\n" if defined $fh;
}
for my $fh ($H, $LH) {
print $fh "/* $license */\n$copyright\n";
}
sub bit_def($) {
my $bit = shift @_;
return "BIT($bit)" if defined $kernel;
return "(1U << $bit)" if $bit =~ /^[a-zA-Z0-9_]+$/;
return "(1U << ($bit))";
}
print $H <<EOF
#ifndef __${uc_header}__
#define __${uc_header}__
EOF
;
print $H "#include <linux/bits.h>\n\n" if defined $kernel;
print $H <<EOF
#define CCS_FL_BASE 16
EOF
;
print $H "#define CCS_FL_16BIT " . bit_def("CCS_FL_BASE") . "\n";
print $H "#define CCS_FL_32BIT " . bit_def("CCS_FL_BASE + 1") . "\n";
print $H "#define CCS_FL_FLOAT_IREAL " . bit_def("CCS_FL_BASE + 2") . "\n";
print $H "#define CCS_FL_IREAL " . bit_def("CCS_FL_BASE + 3") . "\n";
print $H <<EOF
#define CCS_R_ADDR(r) ((r) & 0xffff)
EOF
;
print $A <<EOF
#include <stdint.h>
#include <stdio.h>
#include "ccs-extra.h"
#include "ccs-regs.h"
EOF
if defined $A;
my $uc_limith = basename uc $limith;
$uc_limith =~ s/[^A-Z0-9]/_/g;
print $LH <<EOF
#ifndef __${uc_limith}__
#define __${uc_limith}__
$lh_hdr
struct ccs_limit {
$uint32_t reg;
$uint16_t size;
$uint16_t flags;
const char *name;
};
EOF
;
print $LH "#define CCS_L_FL_SAME_REG " . bit_def(0) . "\n\n";
print $LH <<EOF
extern const struct ccs_limit ccs_limits[];
EOF
;
print $LC <<EOF
#include "ccs-limits.h"
#include "ccs-regs.h"
const struct ccs_limit ccs_limits[] = {
EOF
;
my $limitcount = 0;
my $argdescs;
my $reglist = "const struct ccs_reg_desc ccs_reg_desc[] = {\n";
sub name_split($$) {
my ($name, $addr) = @_;
my $args;
$name =~ /([^\(]+?)(\(.*)/;
($name, $args) = ($1, $2);
$args = [split /,\s*/, $args];
foreach my $t (@$args) {
$t =~ s/[\(\)]//g;
$t =~ s/\//\\\//g;
}
return ($name, $addr, $args);
}
sub tabconv($) {
$_ = shift;
my @l = split "\n", $_;
map {
s/ {8,8}/\t/g;
s/\t\K +//;
} @l;
return (join "\n", @l) . "\n";
}
sub elem_size(@) {
my @flags = @_;
return 2 if grep /^16$/, @flags;
return 4 if grep /^32$/, @flags;
return 1;
}
sub arr_size($) {
my $this = $_[0];
my $size = $this->{elsize};
my $h = $this->{argparams};
foreach my $arg (@{$this->{args}}) {
my $apref = $h->{$arg};
$size *= $apref->{max} - $apref->{min} + 1;
}
return $size;
}
sub print_args($$$) {
my ($this, $postfix, $is_same_reg) = @_;
my ($args, $argparams, $name) =
($this->{args}, $this->{argparams}, $this->{name});
my $varname = "ccs_reg_arg_" . (lc $name) . $postfix;
my @mins;
my @sorted_args = @{$this->{sorted_args}};
my $lim_arg;
my $size = arr_size($this);
$argdescs .= "static const struct ccs_reg_arg " . $varname . "[] = {\n";
foreach my $sorted_arg (@sorted_args) {
push @mins, $argparams->{$sorted_arg}->{min};
}
foreach my $sorted_arg (@sorted_args) {
my $h = $argparams->{$sorted_arg};
$argdescs .= "\t{ \"$sorted_arg\", $h->{min}, $h->{max}, $h->{elsize} },\n";
$lim_arg .= defined $lim_arg ? ", $h->{min}" : "$h->{min}";
}
$argdescs .= "};\n\n";
$reglist .= "\t{ CCS_R_" . (uc $name) . "(" . (join ",", (@mins)) .
"), $size, sizeof($varname) / sizeof(*$varname)," .
" \"" . (lc $name) . "\", $varname },\n";
print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . "($lim_arg), " .
$size . ", " . ($is_same_reg ? "CCS_L_FL_SAME_REG" : "0") .
", \"$name" . (defined $this->{discontig} ? " $lim_arg" : "") . "\" },\n"
if is_limit_reg $this->{base_addr};
}
my $hdr_data;
while (<$R>) {
chop;
s/^\s*//;
next if /^[#;]/ || /^$/;
if (s/^-\s*//) {
if (s/^b\s*//) {
my ($bit, $addr) = split /\t+/;
$bit = uc $bit;
$hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) ."_$bit", bit_def($addr) . "\n";
} elsif (s/^f\s*//) {
s/[,\.-]/_/g;
my @a = split /\s+/;
my ($msb, $lsb, $this_field) = reverse @a;
@a = ( { "name" => "SHIFT", "addr" => $lsb, "fmt" => "%uU", },
{ "name" => "MASK", "addr" => (1 << ($msb + 1)) - 1 - ((1 << $lsb) - 1), "fmt" => "0x%" . join(".", ($this{"elsize"} >> 2) x 2) . "x" } );
$this{"field"} = $this_field;
foreach my $ar (@a) {
#print $ar->{fmt}."\n";
$hdr_data .= sprintf "#define %-62s " . $ar->{"fmt"} . "\n", "CCS_" . (uc $this{"name"}) . (defined $this_field ? "_" . uc $this_field : "") . "_" . $ar->{"name"}, $ar->{"addr"} . "\n";
}
} elsif (s/^e\s*//) {
s/[,\.-]/_/g;
my ($enum, $addr) = split /\s+/;
$enum = uc $enum;
$hdr_data .= sprintf "#define %-62s %s", "CCS_" . (uc ${this{name}}) . (defined $this{"field"} ? "_" . uc $this{"field"} : "") ."_$enum", $addr . ($addr =~ /0x/i ? "" : "U") . "\n";
} elsif (s/^l\s*//) {
my ($arg, $min, $max, $elsize, @discontig) = split /\s+/;
my $size;
foreach my $num ($min, $max) {
$num = hex $num if $num =~ /0x/i;
}
$hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MIN_$arg"), $min . ($min =~ /0x/i ? "" : "U") . "\n";
$hdr_data .= sprintf "#define %-62s %s", "CCS_LIM_" . (uc ${this{name}} . "_MAX_$arg"), $max . ($max =~ /0x/i ? "" : "U") . "\n";
my $h = $this{argparams};
$h->{$arg} = { "min" => $min,
"max" => $max,
"elsize" => $elsize =~ /^0x/ ? hex $elsize : $elsize,
"discontig" => \@discontig };
$this{discontig} = $arg if @discontig;
next if $#{$this{args}} + 1 != scalar keys %{$this{argparams}};
my $reg_formula = "($this{addr}";
my $lim_formula;
foreach my $arg (@{$this{args}}) {
my $d = $h->{$arg}->{discontig};
my $times = $h->{$arg}->{elsize} != 1 ?
" * " . $h->{$arg}->{elsize} : "";
if (@$d) {
my ($lim, $offset) = split /,/, $d->[0];
$reg_formula .= " + (($arg) < $lim ? ($arg)$times : $offset + (($arg) - $lim)$times)";
} else {
$reg_formula .= " + ($arg)$times";
}
$lim_formula .= (defined $lim_formula ? " + " : "") . "($arg)$times";
}
$reg_formula .= ")\n";
$lim_formula =~ s/^\(([a-z0-9]+)\)$/$1/i;
print $H tabconv sprintf("#define %-62s %s", "CCS_R_" . (uc $this{name}) .
$this{arglist}, $reg_formula);
print $H tabconv $hdr_data;
undef $hdr_data;
# Sort arguments in descending order by size
@{$this{sorted_args}} = sort {
$h->{$a}->{elsize} <= $h->{$b}->{elsize}
} @{$this{args}};
if (defined $this{discontig}) {
my $da = $this{argparams}->{$this{discontig}};
my ($first_discontig) = split /,/, $da->{discontig}->[0];
my $max = $da->{max};
$da->{max} = $first_discontig - 1;
print_args(\%this, "", 0);
$da->{min} = $da->{max} + 1;
$da->{max} = $max;
print_args(\%this, $first_discontig, 1);
} else {
print_args(\%this, "", 0);
}
next unless is_limit_reg $this{base_addr};
print $LH tabconv sprintf "#define %-63s%s\n",
"CCS_L_" . (uc $this{name}) . "_OFFSET(" .
(join ", ", @{$this{args}}) . ")", "($lim_formula)";
}
if (! @{$this{args}}) {
print $H tabconv($hdr_data);
undef $hdr_data;
}
next;
}
my ($name, $addr, @flags) = split /\t+/, $_;
my $args = [];
my $sp;
($name, $addr, $args) = name_split($name, $addr) if /\(.*\)/;
$name =~ s/[,\.-]/_/g;
my $flagstring = "";
my $size = elem_size(@flags);
$flagstring .= "| CCS_FL_16BIT " if $size eq "2";
$flagstring .= "| CCS_FL_32BIT " if $size eq "4";
$flagstring .= "| CCS_FL_FLOAT_IREAL " if grep /^float_ireal$/, @flags;
$flagstring .= "| CCS_FL_IREAL " if grep /^ireal$/, @flags;
$flagstring =~ s/^\| //;
$flagstring =~ s/ $//;
$flagstring = "($flagstring)" if $flagstring =~ /\|/;
my $base_addr = $addr;
$addr = "($addr | $flagstring)" if $flagstring ne "";
my $arglist = @$args ? "(" . (join ", ", @$args) . ")" : "";
$hdr_data .= sprintf "#define %-62s %s\n", "CCS_R_" . (uc $name), $addr
if !@$args;
$name =~ s/\(.*//;
%this = ( name => $name,
addr => $addr,
base_addr => $base_addr,
argparams => {},
args => $args,
arglist => $arglist,
elsize => $size,
);
if (!@$args) {
$reglist .= "\t{ CCS_R_" . (uc $name) . ", 1, 0, \"" . (lc $name) . "\", NULL },\n";
print $H tabconv $hdr_data;
undef $hdr_data;
print $LC tabconv sprintf "\t{ CCS_R_" . (uc $name) . ", " .
$this{elsize} . ", 0, \"$name\" },\n"
if is_limit_reg $this{base_addr};
}
print $LH tabconv sprintf "#define %-63s%s\n",
"CCS_L_" . (uc $this{name}), $limitcount++
if is_limit_reg $this{base_addr};
}
if (defined $A) {
print $A $argdescs, $reglist;
print $A "\t{ 0 }\n";
print $A "};\n";
}
print $H "\n#endif /* __${uc_header}__ */\n";
print $LH tabconv sprintf "#define %-63s%s\n", "CCS_L_LAST", $limitcount;
print $LH "\n#endif /* __${uc_limith}__ */\n";
print $LC "\t{ 0 } /* Guardian */\n";
print $LC "};\n";
close($R);
close($H);
close($A) if defined $A;
close($LC);
close($LH);

View file

@ -26,6 +26,7 @@ Video4Linux (V4L) drivers
tuners
vimc-devel
zoran
ccs/ccs
Digital TV drivers

View file

@ -244,7 +244,7 @@ Carrier Signal to Noise ratio (:ref:`DTV-STAT-CNR`)
Having it available after inner FEC is more common.
Bit counts post-FEC (:ref:`DTV-STAT-POST-ERROR-BIT-COUNT` and :ref:`DTV-STAT-POST-TOTAL-BIT-COUNT`)
- Those counters measure the number of bits and bit errors errors after
- Those counters measure the number of bits and bit errors after
the forward error correction (FEC) on the inner coding block
(after Viterbi, LDPC or other inner code).
@ -253,7 +253,7 @@ Bit counts post-FEC (:ref:`DTV-STAT-POST-ERROR-BIT-COUNT` and :ref:`DTV-STAT-POS
see :c:type:`fe_status`).
Bit counts pre-FEC (:ref:`DTV-STAT-PRE-ERROR-BIT-COUNT` and :ref:`DTV-STAT-PRE-TOTAL-BIT-COUNT`)
- Those counters measure the number of bits and bit errors errors before
- Those counters measure the number of bits and bit errors before
the forward error correction (FEC) on the inner coding block
(before Viterbi, LDPC or other inner code).
@ -263,7 +263,7 @@ Bit counts pre-FEC (:ref:`DTV-STAT-PRE-ERROR-BIT-COUNT` and :ref:`DTV-STAT-PRE-T
after ``FE_HAS_VITERBI``, see :c:type:`fe_status`).
Block counts (:ref:`DTV-STAT-ERROR-BLOCK-COUNT` and :ref:`DTV-STAT-TOTAL-BLOCK-COUNT`)
- Those counters measure the number of blocks and block errors errors after
- Those counters measure the number of blocks and block errors after
the forward error correction (FEC) on the inner coding block
(before Viterbi, LDPC or other inner code).

View file

@ -335,7 +335,7 @@ current and new values:
union v4l2_ctrl_ptr p_new;
union v4l2_ctrl_ptr p_cur;
If the control has a simple s32 type type, then:
If the control has a simple s32 type, then:
.. code-block:: c
@ -349,7 +349,7 @@ Within the control ops you can freely use these. The val and cur.val speak for
themselves. The p_char pointers point to character buffers of length
ctrl->maximum + 1, and are always 0-terminated.
Unless the control is marked volatile the p_cur field points to the the
Unless the control is marked volatile the p_cur field points to the
current cached control value. When you create a new control this value is made
identical to the default value. After calling v4l2_ctrl_handler_setup() this
value is passed to the hardware. It is generally a good idea to call this

View file

@ -212,7 +212,7 @@ types exist:
========================== ==================== ==============================
The last argument gives you a certain amount of control over the device
device node number used (i.e. the X in ``videoX``). Normally you will pass -1
node number used (i.e. the X in ``videoX``). Normally you will pass -1
to let the v4l2 framework pick the first free number. But sometimes users
want to select a specific node number. It is common that drivers allow
the user to select a specific device node number through a driver module