diff options
84 files changed, 8838 insertions, 570 deletions
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile index 6628b4b9cac4..362520992ced 100644 --- a/Documentation/DocBook/media/Makefile +++ b/Documentation/DocBook/media/Makefile @@ -70,6 +70,8 @@ IOCTLS = \ VIDIOC_SUBDEV_ENUM_MBUS_CODE \ VIDIOC_SUBDEV_ENUM_FRAME_SIZE \ VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \ + VIDIOC_SUBDEV_G_SELECTION \ + VIDIOC_SUBDEV_S_SELECTION \ TYPES = \ $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/linux/videodev2.h) \ @@ -193,7 +195,7 @@ DVB_DOCUMENTED = \ # install_media_images = \ - $(Q)cp $(OBJIMGFILES) $(MEDIA_OBJ_DIR)/media_api + $(Q)cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api $(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64 $(Q)base64 -d $< >$@ diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml index bce97c50391b..87339b2aad78 100644 --- a/Documentation/DocBook/media/v4l/compat.xml +++ b/Documentation/DocBook/media/v4l/compat.xml @@ -2410,6 +2410,21 @@ details.</para> </orderedlist> </section> + <section> + <title>V4L2 in Linux 3.5</title> + <orderedlist> + <listitem> + <para>Added integer menus, the new type will be + V4L2_CTRL_TYPE_INTEGER_MENU.</para> + </listitem> + <listitem> + <para>Added selection API for V4L2 subdev interface: + &VIDIOC-SUBDEV-G-SELECTION; and + &VIDIOC-SUBDEV-S-SELECTION;.</para> + </listitem> + </orderedlist> + </section> + <section id="other"> <title>Relation of V4L2 to other Linux multimedia APIs</title> @@ -2523,6 +2538,10 @@ ioctls.</para> <listitem> <para>Selection API. <xref linkend="selection-api" /></para> </listitem> + <listitem> + <para>Sub-device selection API: &VIDIOC-SUBDEV-G-SELECTION; + and &VIDIOC-SUBDEV-S-SELECTION; ioctls.</para> + </listitem> </itemizedlist> </section> @@ -2538,6 +2557,13 @@ interfaces and should not be implemented in new drivers.</para> <constant>VIDIOC_S_MPEGCOMP</constant> ioctls. Use Extended Controls, <xref linkend="extended-controls" />.</para> </listitem> + <listitem> + <para><constant>VIDIOC_SUBDEV_G_CROP</constant> and + <constant>VIDIOC_SUBDEV_S_CROP</constant> ioctls. Use + <constant>VIDIOC_SUBDEV_G_SELECTION</constant> and + <constant>VIDIOC_SUBDEV_S_SELECTION</constant>, <xref + linkend="vidioc-subdev-g-selection" />.</para> + </listitem> </itemizedlist> </section> </section> diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml index b84f25e9cc87..5038a3a9a24c 100644 --- a/Documentation/DocBook/media/v4l/controls.xml +++ b/Documentation/DocBook/media/v4l/controls.xml @@ -3486,7 +3486,7 @@ interface and may change in the future.</para> from RGB to Y'CbCr color space. </entry> </row> - <row> + <row id = "v4l2-jpeg-chroma-subsampling"> <entrytbl spanname="descr" cols="2"> <tbody valign="top"> <row> diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml index 0916a7343a16..4afcbbec5eda 100644 --- a/Documentation/DocBook/media/v4l/dev-subdev.xml +++ b/Documentation/DocBook/media/v4l/dev-subdev.xml @@ -76,11 +76,12 @@ <wordasword>format</wordasword> means the combination of media bus data format, frame width and frame height.</para></note> - <para>Image formats are typically negotiated on video capture and output - devices using the <link linkend="crop">cropping and scaling</link> ioctls. - The driver is responsible for configuring every block in the video pipeline - according to the requested format at the pipeline input and/or - output.</para> + <para>Image formats are typically negotiated on video capture and + output devices using the format and <link + linkend="vidioc-subdev-g-selection">selection</link> ioctls. The + driver is responsible for configuring every block in the video + pipeline according to the requested format at the pipeline input + and/or output.</para> <para>For complex devices, such as often found in embedded systems, identical image sizes at the output of a pipeline can be achieved using @@ -276,11 +277,11 @@ </section> <section> - <title>Cropping and scaling</title> + <title>Selections: cropping, scaling and composition</title> <para>Many sub-devices support cropping frames on their input or output pads (or possible even on both). Cropping is used to select the area of - interest in an image, typically on a video sensor or video decoder. It can + interest in an image, typically on an image sensor or a video decoder. It can also be used as part of digital zoom implementations to select the area of the image that will be scaled up.</para> @@ -288,26 +289,179 @@ &v4l2-rect; by the coordinates of the top left corner and the rectangle size. Both the coordinates and sizes are expressed in pixels.</para> - <para>The crop rectangle is retrieved and set using the - &VIDIOC-SUBDEV-G-CROP; and &VIDIOC-SUBDEV-S-CROP; ioctls. Like for pad - formats, drivers store try and active crop rectangles. The format - negotiation mechanism applies to crop settings as well.</para> - - <para>On input pads, cropping is applied relatively to the current pad - format. The pad format represents the image size as received by the - sub-device from the previous block in the pipeline, and the crop rectangle - represents the sub-image that will be transmitted further inside the - sub-device for processing. The crop rectangle be entirely containted - inside the input image size.</para> - - <para>Input crop rectangle are reset to their default value when the input - image format is modified. Drivers should use the input image size as the - crop rectangle default value, but hardware requirements may prevent this. - </para> + <para>As for pad formats, drivers store try and active + rectangles for the selection targets of ACTUAL type <xref + linkend="v4l2-subdev-selection-targets">.</xref></para> + + <para>On sink pads, cropping is applied relative to the + current pad format. The pad format represents the image size as + received by the sub-device from the previous block in the + pipeline, and the crop rectangle represents the sub-image that + will be transmitted further inside the sub-device for + processing.</para> + + <para>The scaling operation changes the size of the image by + scaling it to new dimensions. The scaling ratio isn't specified + explicitly, but is implied from the original and scaled image + sizes. Both sizes are represented by &v4l2-rect;.</para> + + <para>Scaling support is optional. When supported by a subdev, + the crop rectangle on the subdev's sink pad is scaled to the + size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL + using <constant>V4L2_SUBDEV_SEL_COMPOSE_ACTUAL</constant> + selection target on the same pad. If the subdev supports scaling + but not composing, the top and left values are not used and must + always be set to zero.</para> + + <para>On source pads, cropping is similar to sink pads, with the + exception that the source size from which the cropping is + performed, is the COMPOSE rectangle on the sink pad. In both + sink and source pads, the crop rectangle must be entirely + contained inside the source image size for the crop + operation.</para> + + <para>The drivers should always use the closest possible + rectangle the user requests on all selection targets, unless + specifically told otherwise. + <constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant> and + <constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant> flags may be + used to round the image size either up or down. <xref + linkend="v4l2-subdev-selection-flags"></xref></para> + </section> + + <section> + <title>Types of selection targets</title> + + <section> + <title>ACTUAL targets</title> + + <para>ACTUAL targets reflect the actual hardware configuration + at any point of time. There is a BOUNDS target + corresponding to every ACTUAL.</para> + </section> + + <section> + <title>BOUNDS targets</title> + + <para>BOUNDS targets is the smallest rectangle that contains + all valid ACTUAL rectangles. It may not be possible to set the + ACTUAL rectangle as large as the BOUNDS rectangle, however. + This may be because e.g. a sensor's pixel array is not + rectangular but cross-shaped or round. The maximum size may + also be smaller than the BOUNDS rectangle.</para> + </section> - <para>Cropping behaviour on output pads is not defined.</para> + </section> + + <section> + <title>Order of configuration and format propagation</title> + + <para>Inside subdevs, the order of image processing steps will + always be from the sink pad towards the source pad. This is also + reflected in the order in which the configuration must be + performed by the user: the changes made will be propagated to + any subsequent stages. If this behaviour is not desired, the + user must set + <constant>V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG</constant> flag. This + flag causes no propagation of the changes are allowed in any + circumstances. This may also cause the accessed rectangle to be + adjusted by the driver, depending on the properties of the + underlying hardware.</para> + + <para>The coordinates to a step always refer to the actual size + of the previous step. The exception to this rule is the source + compose rectangle, which refers to the sink compose bounds + rectangle --- if it is supported by the hardware.</para> + + <orderedlist> + <listitem>Sink pad format. The user configures the sink pad + format. This format defines the parameters of the image the + entity receives through the pad for further processing.</listitem> + + <listitem>Sink pad actual crop selection. The sink pad crop + defines the crop performed to the sink pad format.</listitem> + + <listitem>Sink pad actual compose selection. The size of the + sink pad compose rectangle defines the scaling ratio compared + to the size of the sink pad crop rectangle. The location of + the compose rectangle specifies the location of the actual + sink compose rectangle in the sink compose bounds + rectangle.</listitem> + + <listitem>Source pad actual crop selection. Crop on the source + pad defines crop performed to the image in the sink compose + bounds rectangle.</listitem> + + <listitem>Source pad format. The source pad format defines the + output pixel format of the subdev, as well as the other + parameters with the exception of the image width and height. + Width and height are defined by the size of the source pad + actual crop selection.</listitem> + </orderedlist> + + <para>Accessing any of the above rectangles not supported by the + subdev will return <constant>EINVAL</constant>. Any rectangle + referring to a previous unsupported rectangle coordinates will + instead refer to the previous supported rectangle. For example, + if sink crop is not supported, the compose selection will refer + to the sink pad format dimensions instead.</para> + + <figure id="subdev-image-processing-crop"> + <title>Image processing in subdevs: simple crop example</title> + <mediaobject> + <imageobject> + <imagedata fileref="subdev-image-processing-crop.svg" + format="SVG" scale="200" /> + </imageobject> + </mediaobject> + </figure> + + <para>In the above example, the subdev supports cropping on its + sink pad. To configure it, the user sets the media bus format on + the subdev's sink pad. Now the actual crop rectangle can be set + on the sink pad --- the location and size of this rectangle + reflect the location and size of a rectangle to be cropped from + the sink format. The size of the sink crop rectangle will also + be the size of the format of the subdev's source pad.</para> + + <figure id="subdev-image-processing-scaling-multi-source"> + <title>Image processing in subdevs: scaling with multiple sources</title> + <mediaobject> + <imageobject> + <imagedata fileref="subdev-image-processing-scaling-multi-source.svg" + format="SVG" scale="200" /> + </imageobject> + </mediaobject> + </figure> + + <para>In this example, the subdev is capable of first cropping, + then scaling and finally cropping for two source pads + individually from the resulting scaled image. The location of + the scaled image in the cropped image is ignored in sink compose + target. Both of the locations of the source crop rectangles + refer to the sink scaling rectangle, independently cropping an + area at location specified by the source crop rectangle from + it.</para> + + <figure id="subdev-image-processing-full"> + <title>Image processing in subdevs: scaling and composition + with multiple sinks and sources</title> + <mediaobject> + <imageobject> + <imagedata fileref="subdev-image-processing-full.svg" + format="SVG" scale="200" /> + </imageobject> + </mediaobject> + </figure> + + <para>The subdev driver supports two sink pads and two source + pads. The images from both of the sink pads are individually + cropped, then scaled and further composed on the composition + bounds rectangle. From that, two independent streams are cropped + and sent out of the subdev from the source pads.</para> </section> + </section> &sub-subdev-formats; diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia b/Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia new file mode 100644 index 000000000000..e32ba5362e1d --- /dev/null +++ b/Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia @@ -0,0 +1,614 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/"> + <dia:diagramdata> + <dia:attribute name="background"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="pagebreak"> + <dia:color val="#000099"/> + </dia:attribute> + <dia:attribute name="paper"> + <dia:composite type="paper"> + <dia:attribute name="name"> + <dia:string>#A4#</dia:string> + </dia:attribute> + <dia:attribute name="tmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="bmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="lmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="rmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="is_portrait"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="scaling"> + <dia:real val="0.49000000953674316"/> + </dia:attribute> + <dia:attribute name="fitto"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="grid"> + <dia:composite type="grid"> + <dia:attribute name="width_x"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="width_y"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="visible_x"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="visible_y"> + <dia:int val="1"/> + </dia:attribute> + <dia:composite type="color"/> + </dia:composite> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#d8e5e5"/> + </dia:attribute> + <dia:attribute name="guides"> + <dia:composite type="guides"> + <dia:attribute name="hguides"/> + <dia:attribute name="vguides"/> + </dia:composite> + </dia:attribute> + </dia:diagramdata> + <dia:layer name="Background" visible="true" active="true"> + <dia:object type="Standard - Box" version="0" id="O0"> + <dia:attribute name="obj_pos"> + <dia:point val="-0.4,6.5"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-0.45,6.45;23.1387,16.2"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-0.4,6.5"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="23.48871579904775"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="9.6500000000000004"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O1"> + <dia:attribute name="obj_pos"> + <dia:point val="0.225,9.45"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.175,9.4;8.225,14.7"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="0.225,9.45"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="7.9499999999999975"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="5.1999999999999975"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O2"> + <dia:attribute name="obj_pos"> + <dia:point val="3.175,10.55"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.125,10.5;7.925,14.45"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="3.175,10.55"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="4.6999999999999975"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.8499999999999979"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O3"> + <dia:attribute name="obj_pos"> + <dia:point val="3.725,11.3875"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.725,10.7925;6.6025,13.14"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink +crop +selection#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="3.725,11.3875"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O4"> + <dia:attribute name="obj_pos"> + <dia:point val="1.475,7.9"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="1.475,7.305;1.475,8.0525"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>##</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="1.475,7.9"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O5"> + <dia:attribute name="obj_pos"> + <dia:point val="0.426918,7.89569"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.426918,7.30069;3.90942,8.84819"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink media +bus format#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="0.426918,7.89569"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O6"> + <dia:attribute name="obj_pos"> + <dia:point val="17.4887,7.75"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="17.4887,7.155;21.8112,8.7025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#source media +bus format#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="17.4887,7.75"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O7"> + <dia:attribute name="obj_pos"> + <dia:point val="17.5244,9.5417"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="17.4744,9.4917;22.2387,13.35"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="17.5244,9.5417"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="4.6643157990477508"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.758300000000002"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O8"> + <dia:attribute name="obj_pos"> + <dia:point val="17.5244,13.3"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.12132,13.2463;17.5781,14.4537"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="17.5244,13.3"/> + <dia:point val="3.175,14.4"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O7" connection="5"/> + <dia:connection handle="1" to="O2" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O9"> + <dia:attribute name="obj_pos"> + <dia:point val="17.5244,9.5417"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.12162,9.48832;17.5778,10.6034"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="17.5244,9.5417"/> + <dia:point val="3.175,10.55"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O7" connection="0"/> + <dia:connection handle="1" to="O2" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O10"> + <dia:attribute name="obj_pos"> + <dia:point val="22.1887,13.3"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.82132,13.2463;22.2424,14.4537"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="22.1887,13.3"/> + <dia:point val="7.875,14.4"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O7" connection="7"/> + <dia:connection handle="1" to="O2" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O11"> + <dia:attribute name="obj_pos"> + <dia:point val="22.1887,9.5417"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.82161,9.48831;22.2421,10.6034"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="22.1887,9.5417"/> + <dia:point val="7.875,10.55"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O7" connection="2"/> + <dia:connection handle="1" to="O2" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O12"> + <dia:attribute name="obj_pos"> + <dia:point val="23.23,10.5742"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="23.18,10.5242;24.13,11.4742"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="23.23,10.5742"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O13"> + <dia:attribute name="obj_pos"> + <dia:point val="24.08,10.9992"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.03,10.6388;32.4953,11.3624"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="24.08,10.9992"/> + <dia:point val="32.3835,11.0007"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O12" connection="3"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O14"> + <dia:attribute name="obj_pos"> + <dia:point val="25.3454,10.49"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.3454,9.895;29.9904,10.6425"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 1 (source)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="25.3454,10.49"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O15"> + <dia:attribute name="obj_pos"> + <dia:point val="-1.44491,11.6506"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-1.49491,11.6006;-0.54491,12.5506"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-1.44491,11.6506"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O16"> + <dia:attribute name="obj_pos"> + <dia:point val="-9.61991,12.09"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-9.67,11.7149;-1.33311,12.4385"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="-9.61991,12.09"/> + <dia:point val="-1.44491,12.0756"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O15" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O17"> + <dia:attribute name="obj_pos"> + <dia:point val="-7.39291,11.49"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-7.39291,10.895;-3.58791,11.6425"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 0 (sink)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="-7.39291,11.49"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + </dia:layer> +</dia:diagram> diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg b/Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg new file mode 100644 index 000000000000..18b0f5de9ed2 --- /dev/null +++ b/Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"> +<svg width="43cm" height="10cm" viewBox="-194 128 844 196" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="469.774" height="193"/> + <g> + <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/> + </g> + <g> + <rect style="fill: #ffffff" x="63.5" y="211" width="94" height="77"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="63.5" y="211" width="94" height="77"/> + </g> + <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="74.5" y="227.75"> + <tspan x="74.5" y="227.75">sink</tspan> + <tspan x="74.5" y="243.75">crop</tspan> + <tspan x="74.5" y="259.75">selection</tspan> + </text> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158"> + <tspan x="29.5" y="158"></tspan> + </text> + <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914"> + <tspan x="8.53836" y="157.914">sink media</tspan> + <tspan x="8.53836" y="173.914">bus format</tspan> + </text> + <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="349.774" y="155"> + <tspan x="349.774" y="155">source media</tspan> + <tspan x="349.774" y="171">bus format</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="350.488" y="190.834" width="93.2863" height="75.166"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="350.488" y="190.834" width="93.2863" height="75.166"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="266" x2="63.5" y2="288"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="190.834" x2="63.5" y2="211"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="266" x2="157.5" y2="288"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="190.834" x2="157.5" y2="211"/> + <g> + <ellipse style="fill: #ffffff" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="481.6" y1="219.984" x2="637.934" y2="220.012"/> + <polygon style="fill: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="506.908" y="209.8"> + <tspan x="506.908" y="209.8">pad 1 (source)</tspan> + </text> + <g> + <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/> + <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8"> + <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan> + </text> +</svg> diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-full.dia b/Documentation/DocBook/media/v4l/subdev-image-processing-full.dia new file mode 100644 index 000000000000..a0d782927840 --- /dev/null +++ b/Documentation/DocBook/media/v4l/subdev-image-processing-full.dia @@ -0,0 +1,1588 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/"> + <dia:diagramdata> + <dia:attribute name="background"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="pagebreak"> + <dia:color val="#000099"/> + </dia:attribute> + <dia:attribute name="paper"> + <dia:composite type="paper"> + <dia:attribute name="name"> + <dia:string>#A4#</dia:string> + </dia:attribute> + <dia:attribute name="tmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="bmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="lmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="rmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="is_portrait"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="scaling"> + <dia:real val="0.49000000953674316"/> + </dia:attribute> + <dia:attribute name="fitto"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="grid"> + <dia:composite type="grid"> + <dia:attribute name="width_x"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="width_y"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="visible_x"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="visible_y"> + <dia:int val="1"/> + </dia:attribute> + <dia:composite type="color"/> + </dia:composite> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#d8e5e5"/> + </dia:attribute> + <dia:attribute name="guides"> + <dia:composite type="guides"> + <dia:attribute name="hguides"/> + <dia:attribute name="vguides"/> + </dia:composite> + </dia:attribute> + </dia:diagramdata> + <dia:layer name="Background" visible="true" active="true"> + <dia:object type="Standard - Box" version="0" id="O0"> + <dia:attribute name="obj_pos"> + <dia:point val="15.945,6.45"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="15.895,6.4;26.4,18.95"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="15.945,6.45"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="10.404999999254942"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="12.449999999999992"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#ff765a"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O1"> + <dia:attribute name="obj_pos"> + <dia:point val="-0.1,3.65"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-0.15,3.6;40.25,20.85"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-0.1,3.65"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="40.300000000000004"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="17.149999999999999"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O2"> + <dia:attribute name="obj_pos"> + <dia:point val="-1.05,7.9106"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-1.1,7.8606;-0.15,8.8106"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-1.05,7.9106"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O3"> + <dia:attribute name="obj_pos"> + <dia:point val="40.3366,9.8342"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="40.2866,9.7842;41.2366,10.7342"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="40.3366,9.8342"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O4"> + <dia:attribute name="obj_pos"> + <dia:point val="-9.225,8.35"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-9.27509,7.97487;-0.938197,8.69848"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="-9.225,8.35"/> + <dia:point val="-1.05,8.3356"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O2" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O5"> + <dia:attribute name="obj_pos"> + <dia:point val="41.1866,10.2592"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="41.1366,9.89879;49.6019,10.6224"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="41.1866,10.2592"/> + <dia:point val="49.4901,10.2607"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O3" connection="3"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O6"> + <dia:attribute name="obj_pos"> + <dia:point val="-6.998,7.75"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-6.998,7.155;-3.193,7.9025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 0 (sink)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="-6.998,7.75"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O7"> + <dia:attribute name="obj_pos"> + <dia:point val="42.452,9.75"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="42.452,9.155;47.097,9.9025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 2 (source)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="42.452,9.75"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O8"> + <dia:attribute name="obj_pos"> + <dia:point val="0.275,6"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.225,5.95;8.275,11.25"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="0.275,6"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="7.9499999999999975"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="5.1999999999999975"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O9"> + <dia:attribute name="obj_pos"> + <dia:point val="3.125,6.8"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.075,6.75;7.875,10.7"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="3.125,6.8"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="4.6999999999999975"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.8499999999999979"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O10"> + <dia:attribute name="obj_pos"> + <dia:point val="1.525,4.45"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="1.525,3.855;1.525,4.6025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>##</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="1.525,4.45"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O11"> + <dia:attribute name="obj_pos"> + <dia:point val="0.476918,4.44569"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.476918,3.85069;3.95942,5.39819"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink media +bus format#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="0.476918,4.44569"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O12"> + <dia:attribute name="obj_pos"> + <dia:point val="16.6822,9.28251"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="16.6322,9.23251;24.9922,17.9564"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="16.6822,9.28251"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="8.2600228398861297"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="8.6238900617957164"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#00ff00"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O13"> + <dia:attribute name="obj_pos"> + <dia:point val="16.6822,17.9064"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.05732,10.5823;16.7499,17.9741"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="16.6822,17.9064"/> + <dia:point val="3.125,10.65"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O12" connection="5"/> + <dia:connection handle="1" to="O9" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O14"> + <dia:attribute name="obj_pos"> + <dia:point val="16.6822,9.28251"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3.06681,6.74181;16.7404,9.3407"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="16.6822,9.28251"/> + <dia:point val="3.125,6.8"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O12" connection="0"/> + <dia:connection handle="1" to="O9" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O15"> + <dia:attribute name="obj_pos"> + <dia:point val="24.9422,17.9064"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.75945,10.5845;25.0077,17.9719"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="24.9422,17.9064"/> + <dia:point val="7.825,10.65"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O12" connection="7"/> + <dia:connection handle="1" to="O9" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O16"> + <dia:attribute name="obj_pos"> + <dia:point val="24.9422,9.28251"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.76834,6.74334;24.9989,9.33917"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="24.9422,9.28251"/> + <dia:point val="7.825,6.8"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O12" connection="2"/> + <dia:connection handle="1" to="O9" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O17"> + <dia:attribute name="obj_pos"> + <dia:point val="16.7352,7.47209"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="16.7352,6.87709;22.5602,8.42459"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink compose +selection (scaling)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="16.7352,7.47209"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#00ff00"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O18"> + <dia:attribute name="obj_pos"> + <dia:point val="20.4661,9.72825"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="20.4161,9.67825;25.5254,13.3509"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="20.4661,9.72825"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.009308462554376"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5726155970598077"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O19"> + <dia:attribute name="obj_pos"> + <dia:point val="34.475,5.2564"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="34.475,4.6614;38.7975,6.2089"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#source media +bus format#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="34.475,5.2564"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O20"> + <dia:attribute name="obj_pos"> + <dia:point val="34.4244,8.6917"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="34.3744,8.6417;39.4837,12.3143"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="34.4244,8.6917"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.009308462554376"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5726155970598077"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O21"> + <dia:attribute name="obj_pos"> + <dia:point val="34.4244,12.2643"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="20.4125,12.2107;34.478,13.3545"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.4244,12.2643"/> + <dia:point val="20.4661,13.3009"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O20" connection="5"/> + <dia:connection handle="1" to="O18" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O22"> + <dia:attribute name="obj_pos"> + <dia:point val="34.4244,8.6917"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="20.4125,8.63813;34.478,9.78182"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.4244,8.6917"/> + <dia:point val="20.4661,9.72825"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O20" connection="0"/> + <dia:connection handle="1" to="O18" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O23"> + <dia:attribute name="obj_pos"> + <dia:point val="39.4337,12.2643"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.4218,12.2107;39.4873,13.3545"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="39.4337,12.2643"/> + <dia:point val="25.4754,13.3009"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O20" connection="7"/> + <dia:connection handle="1" to="O18" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O24"> + <dia:attribute name="obj_pos"> + <dia:point val="39.4337,8.6917"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.4218,8.63813;39.4873,9.78182"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="39.4337,8.6917"/> + <dia:point val="25.4754,9.72825"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O20" connection="2"/> + <dia:connection handle="1" to="O18" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O25"> + <dia:attribute name="obj_pos"> + <dia:point val="16.25,5.15"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="16.25,4.555;21.68,6.1025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink compose +bounds selection#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="16.25,5.15"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#ff765a"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O26"> + <dia:attribute name="obj_pos"> + <dia:point val="-1.02991,16.6506"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-1.07991,16.6006;-0.12991,17.5506"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-1.02991,16.6506"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O27"> + <dia:attribute name="obj_pos"> + <dia:point val="-9.20491,17.09"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-9.255,16.7149;-0.918107,17.4385"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="-9.20491,17.09"/> + <dia:point val="-1.02991,17.0756"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O26" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O28"> + <dia:attribute name="obj_pos"> + <dia:point val="-6.95,16.45"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-6.95,15.855;-3.145,16.6025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 1 (sink)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="-6.95,16.45"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O29"> + <dia:attribute name="obj_pos"> + <dia:point val="0.390412,14.64"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.340412,14.59;6.045,18.8"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="0.390412,14.64"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.604587512785236"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="4.1099999999999994"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O30"> + <dia:attribute name="obj_pos"> + <dia:point val="2.645,15.74"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.595,15.69;5.6,18.3"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="2.645,15.74"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="2.904999999254942"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="2.5100000000000016"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O31"> + <dia:attribute name="obj_pos"> + <dia:point val="1.595,12.99"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="1.595,12.395;1.595,13.1425"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>##</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="1.595,12.99"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O32"> + <dia:attribute name="obj_pos"> + <dia:point val="17.945,12.595"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.58596,12.536;18.004,15.799"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="17.945,12.595"/> + <dia:point val="2.645,15.74"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O36" connection="0"/> + <dia:connection handle="1" to="O30" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O33"> + <dia:attribute name="obj_pos"> + <dia:point val="17.945,15.8"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.58772,15.7427;18.0023,18.3073"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="17.945,15.8"/> + <dia:point val="2.645,18.25"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O36" connection="5"/> + <dia:connection handle="1" to="O30" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O34"> + <dia:attribute name="obj_pos"> + <dia:point val="21.7,15.8"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="5.49307,15.7431;21.7569,18.3069"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="21.7,15.8"/> + <dia:point val="5.55,18.25"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O36" connection="7"/> + <dia:connection handle="1" to="O30" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O35"> + <dia:attribute name="obj_pos"> + <dia:point val="21.7,12.595"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="5.49136,12.5364;21.7586,15.7986"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="21.7,12.595"/> + <dia:point val="5.55,15.74"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O36" connection="2"/> + <dia:connection handle="1" to="O30" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O36"> + <dia:attribute name="obj_pos"> + <dia:point val="17.945,12.595"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="17.895,12.545;21.75,15.85"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="17.945,12.595"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="3.7549999992549452"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.2049999992549427"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#00ff00"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O37"> + <dia:attribute name="obj_pos"> + <dia:point val="22.1631,14.2233"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="22.1131,14.1733;25.45,16.7"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="22.1631,14.2233"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="3.2369000000000021"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="2.4267000000000003"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O38"> + <dia:attribute name="obj_pos"> + <dia:point val="34.6714,16.2367"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="34.6214,16.1867;37.9,18.75"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="34.6714,16.2367"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="3.178600000000003"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="2.4632999999999967"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O39"> + <dia:attribute name="obj_pos"> + <dia:point val="34.6714,18.7"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="22.1057,16.5926;34.7288,18.7574"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.6714,18.7"/> + <dia:point val="22.1631,16.65"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O38" connection="5"/> + <dia:connection handle="1" to="O37" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O40"> + <dia:attribute name="obj_pos"> + <dia:point val="34.6714,16.2367"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="22.1058,14.166;34.7287,16.294"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.6714,16.2367"/> + <dia:point val="22.1631,14.2233"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O38" connection="0"/> + <dia:connection handle="1" to="O37" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O41"> + <dia:attribute name="obj_pos"> + <dia:point val="37.85,18.7"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.3425,16.5925;37.9075,18.7575"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="37.85,18.7"/> + <dia:point val="25.4,16.65"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O38" connection="7"/> + <dia:connection handle="1" to="O37" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O42"> + <dia:attribute name="obj_pos"> + <dia:point val="37.85,16.2367"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.3427,14.166;37.9073,16.294"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="37.85,16.2367"/> + <dia:point val="25.4,14.2233"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O38" connection="2"/> + <dia:connection handle="1" to="O37" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O43"> + <dia:attribute name="obj_pos"> + <dia:point val="40.347,16.7742"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="40.297,16.7242;41.247,17.6742"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="40.347,16.7742"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O44"> + <dia:attribute name="obj_pos"> + <dia:point val="41.197,17.1992"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="41.147,16.8388;49.6123,17.5624"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="41.197,17.1992"/> + <dia:point val="49.5005,17.2007"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O43" connection="3"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O45"> + <dia:attribute name="obj_pos"> + <dia:point val="42.4624,16.69"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="42.4624,16.095;47.1074,16.8425"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 3 (source)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="42.4624,16.69"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O46"> + <dia:attribute name="obj_pos"> + <dia:point val="9.85,4.55"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="9.85,3.955;12.7275,6.3025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink +crop +selection#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="9.85,4.55"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O47"> + <dia:attribute name="obj_pos"> + <dia:point val="27.65,4.75"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="27.65,4.155;30.5275,6.5025"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#source +crop +selection#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="27.65,4.75"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O48"> + <dia:attribute name="obj_pos"> + <dia:point val="10.55,6.6"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.7135,6.39438;10.6035,7.11605"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="10.55,6.6"/> + <dia:point val="7.825,6.8"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O9" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O49"> + <dia:attribute name="obj_pos"> + <dia:point val="10.45,6.55"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="5.48029,6.48236;10.5176,15.8387"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="10.45,6.55"/> + <dia:point val="5.55,15.74"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O30" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O50"> + <dia:attribute name="obj_pos"> + <dia:point val="27.5246,6.66071"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.406,6.59136;27.594,9.82122"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="27.5246,6.66071"/> + <dia:point val="25.4754,9.72825"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O18" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O51"> + <dia:attribute name="obj_pos"> + <dia:point val="27.5036,6.68935"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="25.2161,6.62775;27.5652,14.331"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="27.5036,6.68935"/> + <dia:point val="25.4,14.2233"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O37" connection="2"/> + </dia:connections> + </dia:object> + </dia:layer> +</dia:diagram> diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-full.svg b/Documentation/DocBook/media/v4l/subdev-image-processing-full.svg new file mode 100644 index 000000000000..3322cf4c0093 --- /dev/null +++ b/Documentation/DocBook/media/v4l/subdev-image-processing-full.svg @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"> +<svg width="59cm" height="18cm" viewBox="-186 71 1178 346" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g> + <rect style="fill: #ffffff" x="318.9" y="129" width="208.1" height="249"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff765a" x="318.9" y="129" width="208.1" height="249"/> + </g> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-2" y="73" width="806" height="343"/> + <g> + <ellipse style="fill: #ffffff" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/> + </g> + <g> + <ellipse style="fill: #ffffff" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.5" y1="167" x2="-30.7361" y2="166.729"/> + <polygon style="fill: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.732" y1="205.184" x2="980.066" y2="205.212"/> + <polygon style="fill: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139.96" y="155"> + <tspan x="-139.96" y="155">pad 0 (sink)</tspan> + </text> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.04" y="195"> + <tspan x="849.04" y="195">pad 2 (source)</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="5.5" y="120" width="159" height="104"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="5.5" y="120" width="159" height="104"/> + </g> + <g> + <rect style="fill: #ffffff" x="62.5" y="136" width="94" height="77"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="62.5" y="136" width="94" height="77"/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="30.5" y="89"> + <tspan x="30.5" y="89"></tspan> + </text> + <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="9.53836" y="88.9138"> + <tspan x="9.53836" y="88.9138">sink media</tspan> + <tspan x="9.53836" y="104.914">bus format</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="62.5" y2="213"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="62.5" y2="136"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="156.5" y2="213"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="156.5" y2="136"/> + <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442"> + <tspan x="334.704" y="149.442">sink compose</tspan> + <tspan x="334.704" y="165.442">selection (scaling)</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="409.322" y="194.565" width="100.186" height="71.4523"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="409.322" y="194.565" width="100.186" height="71.4523"/> + </g> + <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="689.5" y="105.128"> + <tspan x="689.5" y="105.128">source media</tspan> + <tspan x="689.5" y="121.128">bus format</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="688.488" y="173.834" width="100.186" height="71.4523"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="688.488" y="173.834" width="100.186" height="71.4523"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="245.286" x2="409.322" y2="266.018"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="173.834" x2="409.322" y2="194.565"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="245.286" x2="509.508" y2="266.018"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="173.834" x2="509.508" y2="194.565"/> + <text style="fill: #ff765a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="325" y="103"> + <tspan x="325" y="103">sink compose</tspan> + <tspan x="325" y="119">bounds selection</tspan> + </text> + <g> + <ellipse style="fill: #ffffff" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.098" y1="341.8" x2="-30.3343" y2="341.529"/> + <polygon style="fill: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139" y="329"> + <tspan x="-139" y="329">pad 1 (sink)</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="7.80824" y="292.8" width="112.092" height="82.2"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="7.80824" y="292.8" width="112.092" height="82.2"/> + </g> + <g> + <rect style="fill: #ffffff" x="52.9" y="314.8" width="58.1" height="50.2"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="52.9" y="314.8" width="58.1" height="50.2"/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="31.9" y="259.8"> + <tspan x="31.9" y="259.8"></tspan> + </text> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="251.9" x2="52.9" y2="314.8"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="316" x2="52.9" y2="365"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="316" x2="111" y2="365"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="251.9" x2="111" y2="314.8"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="358.9" y="251.9" width="75.1" height="64.1"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="443.262" y="284.466" width="64.738" height="48.534"/> + <g> + <rect style="fill: #ffffff" x="693.428" y="324.734" width="63.572" height="49.266"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="693.428" y="324.734" width="63.572" height="49.266"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="374" x2="443.262" y2="333"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="324.734" x2="443.262" y2="284.466"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="374" x2="508" y2="333"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="324.734" x2="508" y2="284.466"/> + <g> + <ellipse style="fill: #ffffff" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.94" y1="343.984" x2="980.274" y2="344.012"/> + <polygon style="fill: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.248" y="333.8"> + <tspan x="849.248" y="333.8">pad 3 (source)</tspan> + </text> + <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="197" y="91"> + <tspan x="197" y="91">sink</tspan> + <tspan x="197" y="107">crop</tspan> + <tspan x="197" y="123">selection</tspan> + </text> + <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="553" y="95"> + <tspan x="553" y="95">source</tspan> + <tspan x="553" y="111">crop</tspan> + <tspan x="553" y="127">selection</tspan> + </text> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="211" y1="132" x2="166.21" y2="135.287"/> + <polygon style="fill: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="209" y1="131" x2="115.581" y2="306.209"/> + <polygon style="fill: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.492" y1="133.214" x2="514.916" y2="186.469"/> + <polygon style="fill: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.072" y1="133.787" x2="510.618" y2="275.089"/> + <polygon style="fill: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/> + </g> +</svg> diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia b/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia new file mode 100644 index 000000000000..0cd50a7bda80 --- /dev/null +++ b/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia @@ -0,0 +1,1152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/"> + <dia:diagramdata> + <dia:attribute name="background"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="pagebreak"> + <dia:color val="#000099"/> + </dia:attribute> + <dia:attribute name="paper"> + <dia:composite type="paper"> + <dia:attribute name="name"> + <dia:string>#A4#</dia:string> + </dia:attribute> + <dia:attribute name="tmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="bmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="lmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="rmargin"> + <dia:real val="2.8222000598907471"/> + </dia:attribute> + <dia:attribute name="is_portrait"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="scaling"> + <dia:real val="0.49000000953674316"/> + </dia:attribute> + <dia:attribute name="fitto"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="grid"> + <dia:composite type="grid"> + <dia:attribute name="width_x"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="width_y"> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="visible_x"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="visible_y"> + <dia:int val="1"/> + </dia:attribute> + <dia:composite type="color"/> + </dia:composite> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#d8e5e5"/> + </dia:attribute> + <dia:attribute name="guides"> + <dia:composite type="guides"> + <dia:attribute name="hguides"/> + <dia:attribute name="vguides"/> + </dia:composite> + </dia:attribute> + </dia:diagramdata> + <dia:layer name="Background" visible="true" active="true"> + <dia:object type="Standard - Box" version="0" id="O0"> + <dia:attribute name="obj_pos"> + <dia:point val="-0.4,6.5"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-0.45,6.45;39.95,22.9"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-0.4,6.5"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="40.299999999999997"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="16.349999999999998"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O1"> + <dia:attribute name="obj_pos"> + <dia:point val="0.225,9.45"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.175,9.4;8.225,14.7"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="0.225,9.45"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="7.9499999999999975"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="5.1999999999999975"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O2"> + <dia:attribute name="obj_pos"> + <dia:point val="2.475,10.2"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.425,10.15;7.225,14.1"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="2.475,10.2"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="4.6999999999999975"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.8499999999999979"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O3"> + <dia:attribute name="obj_pos"> + <dia:point val="3,11.2"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="3,10.605;5.8775,12.9525"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink +crop +selection#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="3,11.2"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#0000ff"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O4"> + <dia:attribute name="obj_pos"> + <dia:point val="1.475,7.9"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="1.475,7.305;1.475,8.0525"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>##</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="1.475,7.9"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O5"> + <dia:attribute name="obj_pos"> + <dia:point val="0.426918,7.89569"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="0.426918,7.30069;3.90942,8.84819"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink media +bus format#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="0.426918,7.89569"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#a52a2a"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O6"> + <dia:attribute name="obj_pos"> + <dia:point val="16.6822,9.28251"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="16.6322,9.23251;24.9922,17.9564"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="16.6822,9.28251"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="8.2600228398861297"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="8.6238900617957164"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#00ff00"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O7"> + <dia:attribute name="obj_pos"> + <dia:point val="16.6822,17.9064"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.41365,13.9886;16.7436,17.9678"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="16.6822,17.9064"/> + <dia:point val="2.475,14.05"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O6" connection="5"/> + <dia:connection handle="1" to="O2" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O8"> + <dia:attribute name="obj_pos"> + <dia:point val="16.6822,9.28251"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="2.42188,9.22939;16.7353,10.2531"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="16.6822,9.28251"/> + <dia:point val="2.475,10.2"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O6" connection="0"/> + <dia:connection handle="1" to="O2" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O9"> + <dia:attribute name="obj_pos"> + <dia:point val="24.9422,17.9064"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.11553,13.9905;25.0017,17.9659"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="24.9422,17.9064"/> + <dia:point val="7.175,14.05"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O6" connection="7"/> + <dia:connection handle="1" to="O2" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O10"> + <dia:attribute name="obj_pos"> + <dia:point val="24.9422,9.28251"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="7.12249,9.23;24.9947,10.2525"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="24.9422,9.28251"/> + <dia:point val="7.175,10.2"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O6" connection="2"/> + <dia:connection handle="1" to="O2" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O11"> + <dia:attribute name="obj_pos"> + <dia:point val="16.7352,7.47209"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="16.7352,6.87709;22.5602,8.42459"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#sink compose +selection (scaling)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="16.7352,7.47209"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#00ff00"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O12"> + <dia:attribute name="obj_pos"> + <dia:point val="19.1161,9.97825"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="19.0661,9.92825;24.1754,13.6009"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="19.1161,9.97825"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.009308462554376"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5726155970598077"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O13"> + <dia:attribute name="obj_pos"> + <dia:point val="27.1661,7.47209"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="27.1661,6.87709;30.0436,9.22459"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#source +crop +selection#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="27.1661,7.47209"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O14"> + <dia:attribute name="obj_pos"> + <dia:point val="34.575,7.8564"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="34.575,7.2614;38.8975,8.8089"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#source media +bus format#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="34.575,7.8564"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O15"> + <dia:attribute name="obj_pos"> + <dia:point val="34.5244,11.2917"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="34.4744,11.2417;39.5837,14.9143"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="34.5244,11.2917"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.009308462554376"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5726155970598077"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O16"> + <dia:attribute name="obj_pos"> + <dia:point val="34.5244,14.8643"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="19.062,13.4968;34.5785,14.9184"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.5244,14.8643"/> + <dia:point val="19.1161,13.5509"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O15" connection="5"/> + <dia:connection handle="1" to="O12" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O17"> + <dia:attribute name="obj_pos"> + <dia:point val="34.5244,11.2917"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="19.062,9.92418;34.5785,11.3458"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.5244,11.2917"/> + <dia:point val="19.1161,9.97825"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O15" connection="0"/> + <dia:connection handle="1" to="O12" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O18"> + <dia:attribute name="obj_pos"> + <dia:point val="39.5337,14.8643"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.0713,13.4968;39.5878,14.9184"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="39.5337,14.8643"/> + <dia:point val="24.1254,13.5509"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O15" connection="7"/> + <dia:connection handle="1" to="O12" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O19"> + <dia:attribute name="obj_pos"> + <dia:point val="39.5337,11.2917"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.0713,9.92418;39.5878,11.3458"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="39.5337,11.2917"/> + <dia:point val="24.1254,9.97825"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O15" connection="2"/> + <dia:connection handle="1" to="O12" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O20"> + <dia:attribute name="obj_pos"> + <dia:point val="39.98,12.0742"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="39.93,12.0242;40.88,12.9742"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="39.98,12.0742"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O21"> + <dia:attribute name="obj_pos"> + <dia:point val="40.83,12.4992"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="40.78,12.1388;49.2453,12.8624"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="40.83,12.4992"/> + <dia:point val="49.1335,12.5007"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O20" connection="3"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O22"> + <dia:attribute name="obj_pos"> + <dia:point val="42.0954,11.99"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="42.0954,11.395;46.7404,12.1425"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 1 (source)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="42.0954,11.99"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O23"> + <dia:attribute name="obj_pos"> + <dia:point val="-1.44491,11.6506"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-1.49491,11.6006;-0.54491,12.5506"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="-1.44491,11.6506"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O24"> + <dia:attribute name="obj_pos"> + <dia:point val="-9.61991,12.09"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-9.67,11.7149;-1.33311,12.4385"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="-9.61991,12.09"/> + <dia:point val="-1.44491,12.0756"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O23" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O25"> + <dia:attribute name="obj_pos"> + <dia:point val="-7.39291,11.49"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="-7.39291,10.895;-3.58791,11.6425"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 0 (sink)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="-7.39291,11.49"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O26"> + <dia:attribute name="obj_pos"> + <dia:point val="19.4911,13.8333"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="19.4411,13.7833;24.5504,17.4559"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="19.4911,13.8333"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.009308462554376"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5726155970598077"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="false"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Box" version="0" id="O27"> + <dia:attribute name="obj_pos"> + <dia:point val="34.4994,17.2967"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="34.4494,17.2467;39.5587,20.9193"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="34.4994,17.2967"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="5.009308462554376"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="3.5726155970598077"/> + </dia:attribute> + <dia:attribute name="border_width"> + <dia:real val="0.10000000149011612"/> + </dia:attribute> + <dia:attribute name="border_color"> + <dia:color val="#8b6914"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O28"> + <dia:attribute name="obj_pos"> + <dia:point val="34.4994,20.8693"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="19.4311,17.3459;34.5594,20.9293"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.4994,20.8693"/> + <dia:point val="19.4911,17.4059"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O27" connection="5"/> + <dia:connection handle="1" to="O26" connection="5"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O29"> + <dia:attribute name="obj_pos"> + <dia:point val="34.4994,17.2967"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="19.4311,13.7733;34.5594,17.3567"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="34.4994,17.2967"/> + <dia:point val="19.4911,13.8333"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O27" connection="0"/> + <dia:connection handle="1" to="O26" connection="0"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O30"> + <dia:attribute name="obj_pos"> + <dia:point val="39.5087,20.8693"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.4404,17.3459;39.5687,20.9293"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="39.5087,20.8693"/> + <dia:point val="24.5004,17.4059"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O27" connection="7"/> + <dia:connection handle="1" to="O26" connection="7"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O31"> + <dia:attribute name="obj_pos"> + <dia:point val="39.5087,17.2967"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.4404,13.7733;39.5687,17.3567"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="39.5087,17.2967"/> + <dia:point val="24.5004,13.8333"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#e60505"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="4"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O27" connection="2"/> + <dia:connection handle="1" to="O26" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Geometric - Perfect Circle" version="1" id="O32"> + <dia:attribute name="obj_pos"> + <dia:point val="39.855,18.7792"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="39.805,18.7292;40.755,19.6792"/> + </dia:attribute> + <dia:attribute name="meta"> + <dia:composite type="dict"/> + </dia:attribute> + <dia:attribute name="elem_corner"> + <dia:point val="39.855,18.7792"/> + </dia:attribute> + <dia:attribute name="elem_width"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="elem_height"> + <dia:real val="0.84999999999999787"/> + </dia:attribute> + <dia:attribute name="line_width"> + <dia:real val="0.10000000000000001"/> + </dia:attribute> + <dia:attribute name="line_colour"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="fill_colour"> + <dia:color val="#ffffff"/> + </dia:attribute> + <dia:attribute name="show_background"> + <dia:boolean val="true"/> + </dia:attribute> + <dia:attribute name="line_style"> + <dia:enum val="0"/> + <dia:real val="1"/> + </dia:attribute> + <dia:attribute name="flip_horizontal"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="flip_vertical"> + <dia:boolean val="false"/> + </dia:attribute> + <dia:attribute name="subscale"> + <dia:real val="1"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O33"> + <dia:attribute name="obj_pos"> + <dia:point val="40.705,19.2042"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="40.655,18.8438;49.1203,19.5674"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="40.705,19.2042"/> + <dia:point val="49.0085,19.2057"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="0" to="O32" connection="3"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Text" version="1" id="O34"> + <dia:attribute name="obj_pos"> + <dia:point val="41.9704,18.695"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="41.9704,18.1;46.6154,18.8475"/> + </dia:attribute> + <dia:attribute name="text"> + <dia:composite type="text"> + <dia:attribute name="string"> + <dia:string>#pad 2 (source)#</dia:string> + </dia:attribute> + <dia:attribute name="font"> + <dia:font family="sans" style="0" name="Helvetica"/> + </dia:attribute> + <dia:attribute name="height"> + <dia:real val="0.80000000000000004"/> + </dia:attribute> + <dia:attribute name="pos"> + <dia:point val="41.9704,18.695"/> + </dia:attribute> + <dia:attribute name="color"> + <dia:color val="#000000"/> + </dia:attribute> + <dia:attribute name="alignment"> + <dia:enum val="0"/> + </dia:attribute> + </dia:composite> + </dia:attribute> + <dia:attribute name="valign"> + <dia:enum val="3"/> + </dia:attribute> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O35"> + <dia:attribute name="obj_pos"> + <dia:point val="27.3,9.55"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.0146,9.49376;27.3562,10.255"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="27.3,9.55"/> + <dia:point val="24.1254,9.97825"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O12" connection="2"/> + </dia:connections> + </dia:object> + <dia:object type="Standard - Line" version="0" id="O36"> + <dia:attribute name="obj_pos"> + <dia:point val="27.3454,9.53624"/> + </dia:attribute> + <dia:attribute name="obj_bb"> + <dia:rectangle val="24.4311,9.46695;27.4147,13.9265"/> + </dia:attribute> + <dia:attribute name="conn_endpoints"> + <dia:point val="27.3454,9.53624"/> + <dia:point val="24.5004,13.8333"/> + </dia:attribute> + <dia:attribute name="numcp"> + <dia:int val="1"/> + </dia:attribute> + <dia:attribute name="line_color"> + <dia:color val="#a020f0"/> + </dia:attribute> + <dia:attribute name="end_arrow"> + <dia:enum val="22"/> + </dia:attribute> + <dia:attribute name="end_arrow_length"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:attribute name="end_arrow_width"> + <dia:real val="0.5"/> + </dia:attribute> + <dia:connections> + <dia:connection handle="1" to="O26" connection="2"/> + </dia:connections> + </dia:object> + </dia:layer> +</dia:diagram> diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg b/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg new file mode 100644 index 000000000000..2340c0f8bc92 --- /dev/null +++ b/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd"> +<svg width="59cm" height="17cm" viewBox="-194 128 1179 330" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="806" height="327"/> + <g> + <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/> + </g> + <g> + <rect style="fill: #ffffff" x="49.5" y="204" width="94" height="77"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="49.5" y="204" width="94" height="77"/> + </g> + <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="60" y="224"> + <tspan x="60" y="224">sink</tspan> + <tspan x="60" y="240">crop</tspan> + <tspan x="60" y="256">selection</tspan> + </text> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158"> + <tspan x="29.5" y="158"></tspan> + </text> + <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914"> + <tspan x="8.53836" y="157.914">sink media</tspan> + <tspan x="8.53836" y="173.914">bus format</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="49.5" y2="281"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="49.5" y2="204"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="143.5" y2="281"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="143.5" y2="204"/> + <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442"> + <tspan x="334.704" y="149.442">sink compose</tspan> + <tspan x="334.704" y="165.442">selection (scaling)</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="382.322" y="199.565" width="100.186" height="71.4523"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="382.322" y="199.565" width="100.186" height="71.4523"/> + </g> + <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="543.322" y="149.442"> + <tspan x="543.322" y="149.442">source</tspan> + <tspan x="543.322" y="165.442">crop</tspan> + <tspan x="543.322" y="181.442">selection</tspan> + </text> + <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="691.5" y="157.128"> + <tspan x="691.5" y="157.128">source media</tspan> + <tspan x="691.5" y="173.128">bus format</tspan> + </text> + <g> + <rect style="fill: #ffffff" x="690.488" y="225.834" width="100.186" height="71.4523"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="690.488" y="225.834" width="100.186" height="71.4523"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="297.286" x2="382.322" y2="271.018"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="225.834" x2="382.322" y2="199.565"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="297.286" x2="482.508" y2="271.018"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="225.834" x2="482.508" y2="199.565"/> + <g> + <ellipse style="fill: #ffffff" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="816.6" y1="249.984" x2="972.934" y2="250.012"/> + <polygon style="fill: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="841.908" y="239.8"> + <tspan x="841.908" y="239.8">pad 1 (source)</tspan> + </text> + <g> + <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/> + <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8"> + <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan> + </text> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="389.822" y="276.666" width="100.186" height="71.4523"/> + <g> + <rect style="fill: #ffffff" x="689.988" y="345.934" width="100.186" height="71.4523"/> + <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="689.988" y="345.934" width="100.186" height="71.4523"/> + </g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="417.386" x2="389.822" y2="348.118"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="345.934" x2="389.822" y2="276.666"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="417.386" x2="490.008" y2="348.118"/> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="345.934" x2="490.008" y2="276.666"/> + <g> + <ellipse style="fill: #ffffff" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/> + <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="814.1" y1="384.084" x2="970.434" y2="384.112"/> + <polygon style="fill: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/> + </g> + <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="839.408" y="373.9"> + <tspan x="839.408" y="373.9">pad 2 (source)</tspan> + </text> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546" y1="191" x2="492.157" y2="198.263"/> + <polygon style="fill: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/> + </g> + <g> + <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546.908" y1="190.725" x2="495.383" y2="268.548"/> + <polygon style="fill: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/> + <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/> + </g> +</svg> diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml index 8ae38876172e..fbf808d242f7 100644 --- a/Documentation/DocBook/media/v4l/v4l2.xml +++ b/Documentation/DocBook/media/v4l/v4l2.xml @@ -96,6 +96,17 @@ Remote Controller chapter.</contrib> </address> </affiliation> </author> + + <author> + <firstname>Sakari</firstname> + <surname>Ailus</surname> + <contrib>Subdev selections API.</contrib> + <affiliation> + <address> + <email>sakari.ailus@iki.fi</email> + </address> + </affiliation> + </author> </authorgroup> <copyright> @@ -128,6 +139,15 @@ structs, ioctls) must be noted in more detail in the history chapter applications. --> <revision> + <revnumber>3.5</revnumber> + <date>2012-04-02</date> + <authorinitials>sa</authorinitials> + <revremark>Added V4L2_CTRL_TYPE_INTEGER_MENU and V4L2 subdev + selections API. + </revremark> + </revision> + + <revision> <revnumber>3.4</revnumber> <date>2012-01-25</date> <authorinitials>sn</authorinitials> @@ -540,6 +560,7 @@ and discussions on the V4L mailing list.</revremark> &sub-subdev-g-crop; &sub-subdev-g-fmt; &sub-subdev-g-frame-interval; + &sub-subdev-g-selection; &sub-subscribe-event; <!-- End of ioctls. --> &sub-mmap; diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml index b17a7aac6997..27e20bcbdf42 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml @@ -265,6 +265,13 @@ These controls are described in <xref These controls are described in <xref linkend="flash-controls" />.</entry> </row> + <row> + <entry><constant>V4L2_CTRL_CLASS_JPEG</constant></entry> + <entry>0x9d0000</entry> + <entry>The class containing JPEG compression controls. +These controls are described in <xref + linkend="jpeg-controls" />.</entry> + </row> </tbody> </tgroup> </table> diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml index 36660d311b51..505f0206e5bd 100644 --- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml +++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml @@ -215,11 +215,12 @@ the array to zero.</entry> <table pgwide="1" frame="none" id="v4l2-querymenu"> <title>struct <structname>v4l2_querymenu</structname></title> - <tgroup cols="3"> + <tgroup cols="4"> &cs-str; <tbody valign="top"> <row> <entry>__u32</entry> + <entry></entry> <entry><structfield>id</structfield></entry> <entry>Identifies the control, set by the application from the respective &v4l2-queryctrl; @@ -227,18 +228,38 @@ from the respective &v4l2-queryctrl; </row> <row> <entry>__u32</entry> + <entry></entry> <entry><structfield>index</structfield></entry> <entry>Index of the menu item, starting at zero, set by the application.</entry> </row> <row> + <entry>union</entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> + <row> + <entry></entry> <entry>__u8</entry> <entry><structfield>name</structfield>[32]</entry> <entry>Name of the menu item, a NUL-terminated ASCII -string. This information is intended for the user.</entry> +string. This information is intended for the user. This field is valid +for <constant>V4L2_CTRL_FLAG_MENU</constant> type controls.</entry> + </row> + <row> + <entry></entry> + <entry>__s64</entry> + <entry><structfield>value</structfield></entry> + <entry> + Value of the integer menu item. This field is valid for + <constant>V4L2_CTRL_FLAG_INTEGER_MENU</constant> type + controls. + </entry> </row> <row> <entry>__u32</entry> + <entry></entry> <entry><structfield>reserved</structfield></entry> <entry>Reserved for future extensions. Drivers must set the array to zero.</entry> @@ -292,6 +313,20 @@ the menu items can be enumerated with the <constant>VIDIOC_QUERYMENU</constant> ioctl.</entry> </row> <row> + <entry><constant>V4L2_CTRL_TYPE_INTEGER_MENU</constant></entry> + <entry>≥ 0</entry> + <entry>1</entry> + <entry>N-1</entry> + <entry> + The control has a menu of N choices. The values of the + menu items can be enumerated with the + <constant>VIDIOC_QUERYMENU</constant> ioctl. This is + similar to <constant>V4L2_CTRL_TYPE_MENU</constant> + except that instead of strings, the menu items are + signed 64-bit integers. + </entry> + </row> + <row> <entry><constant>V4L2_CTRL_TYPE_BITMASK</constant></entry> <entry>0</entry> <entry>n/a</entry> diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml index 06197323a8cc..4cddd788c589 100644 --- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml @@ -58,9 +58,12 @@ <title>Description</title> <note> - <title>Experimental</title> - <para>This is an <link linkend="experimental">experimental</link> - interface and may change in the future.</para> + <title>Obsolete</title> + + <para>This is an <link linkend="obsolete">obsolete</link> + interface and may be removed in the future. It is superseded by + <link linkend="vidioc-subdev-g-selection">the selection + API</link>.</para> </note> <para>To retrieve the current crop rectangle applications set the diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml new file mode 100644 index 000000000000..208e9f0da3f3 --- /dev/null +++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml @@ -0,0 +1,228 @@ +<refentry id="vidioc-subdev-g-selection"> + <refmeta> + <refentrytitle>ioctl VIDIOC_SUBDEV_G_SELECTION, VIDIOC_SUBDEV_S_SELECTION</refentrytitle> + &manvol; + </refmeta> + + <refnamediv> + <refname>VIDIOC_SUBDEV_G_SELECTION</refname> + <refname>VIDIOC_SUBDEV_S_SELECTION</refname> + <refpurpose>Get or set selection rectangles on a subdev pad</refpurpose> + </refnamediv> + + <refsynopsisdiv> + <funcsynopsis> + <funcprototype> + <funcdef>int <function>ioctl</function></funcdef> + <paramdef>int <parameter>fd</parameter></paramdef> + <paramdef>int <parameter>request</parameter></paramdef> + <paramdef>struct v4l2_subdev_selection *<parameter>argp</parameter></paramdef> + </funcprototype> + </funcsynopsis> + </refsynopsisdiv> + + <refsect1> + <title>Arguments</title> + + <variablelist> + <varlistentry> + <term><parameter>fd</parameter></term> + <listitem> + <para>&fd;</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>request</parameter></term> + <listitem> + <para>VIDIOC_SUBDEV_G_SELECTION, VIDIOC_SUBDEV_S_SELECTION</para> + </listitem> + </varlistentry> + <varlistentry> + <term><parameter>argp</parameter></term> + <listitem> + <para></para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + + <refsect1> + <title>Description</title> + + <note> + <title>Experimental</title> + <para>This is an <link linkend="experimental">experimental</link> + interface and may change in the future.</para> + </note> + + <para>The selections are used to configure various image + processing functionality performed by the subdevs which affect the + image size. This currently includes cropping, scaling and + composition.</para> + + <para>The selection API replaces <link + linkend="vidioc-subdev-g-crop">the old subdev crop API</link>. All + the function of the crop API, and more, are supported by the + selections API.</para> + + <para>See <xref linkend="subdev"></xref> for + more information on how each selection target affects the image + processing pipeline inside the subdevice.</para> + + <section> + <title>Types of selection targets</title> + + <para>There are two types of selection targets: actual and bounds. + The ACTUAL targets are the targets which configure the hardware. + The BOUNDS target will return a rectangle that contain all + possible ACTUAL rectangles.</para> + </section> + + <section> + <title>Discovering supported features</title> + + <para>To discover which targets are supported, the user can + perform <constant>VIDIOC_SUBDEV_G_SELECTION</constant> on them. + Any unsupported target will return + <constant>EINVAL</constant>.</para> + </section> + + <table pgwide="1" frame="none" id="v4l2-subdev-selection-targets"> + <title>V4L2 subdev selection targets</title> + <tgroup cols="3"> + &cs-def; + <tbody valign="top"> + <row> + <entry><constant>V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL</constant></entry> + <entry>0x0000</entry> + <entry>Actual crop. Defines the cropping + performed by the processing step.</entry> + </row> + <row> + <entry><constant>V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS</constant></entry> + <entry>0x0002</entry> + <entry>Bounds of the crop rectangle.</entry> + </row> + <row> + <entry><constant>V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL</constant></entry> + <entry>0x0100</entry> + <entry>Actual compose rectangle. Used to configure scaling + on sink pads and composition on source pads.</entry> + </row> + <row> + <entry><constant>V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS</constant></entry> + <entry>0x0102</entry> + <entry>Bounds of the compose rectangle.</entry> + </row> + </tbody> + </tgroup> + </table> + + <table pgwide="1" frame="none" id="v4l2-subdev-selection-flags"> + <title>V4L2 subdev selection flags</title> + <tgroup cols="3"> + &cs-def; + <tbody valign="top"> + <row> + <entry><constant>V4L2_SUBDEV_SEL_FLAG_SIZE_GE</constant></entry> + <entry>(1 << 0)</entry> <entry>Suggest the driver it + should choose greater or equal rectangle (in size) than + was requested. Albeit the driver may choose a lesser size, + it will only do so due to hardware limitations. Without + this flag (and + <constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant>) the + behaviour is to choose the closest possible + rectangle.</entry> + </row> + <row> + <entry><constant>V4L2_SUBDEV_SEL_FLAG_SIZE_LE</constant></entry> + <entry>(1 << 1)</entry> <entry>Suggest the driver it + should choose lesser or equal rectangle (in size) than was + requested. Albeit the driver may choose a greater size, it + will only do so due to hardware limitations.</entry> + </row> + <row> + <entry><constant>V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG</constant></entry> + <entry>(1 << 2)</entry> + <entry>The configuration should not be propagated to any + further processing steps. If this flag is not given, the + configuration is propagated inside the subdevice to all + further processing steps.</entry> + </row> + </tbody> + </tgroup> + </table> + + <table pgwide="1" frame="none" id="v4l2-subdev-selection"> + <title>struct <structname>v4l2_subdev_selection</structname></title> + <tgroup cols="3"> + &cs-str; + <tbody valign="top"> + <row> + <entry>__u32</entry> + <entry><structfield>which</structfield></entry> + <entry>Active or try selection, from + &v4l2-subdev-format-whence;.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>pad</structfield></entry> + <entry>Pad number as reported by the media framework.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>target</structfield></entry> + <entry>Target selection rectangle. See + <xref linkend="v4l2-subdev-selection-targets">.</xref>.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>flags</structfield></entry> + <entry>Flags. See + <xref linkend="v4l2-subdev-selection-flags">.</xref></entry> + </row> + <row> + <entry>&v4l2-rect;</entry> + <entry><structfield>rect</structfield></entry> + <entry>Selection rectangle, in pixels.</entry> + </row> + <row> + <entry>__u32</entry> + <entry><structfield>reserved</structfield>[8]</entry> + <entry>Reserved for future extensions. Applications and drivers must + set the array to zero.</entry> + </row> + </tbody> + </tgroup> + </table> + + </refsect1> + + <refsect1> + &return-value; + + <variablelist> + <varlistentry> + <term><errorcode>EBUSY</errorcode></term> + <listitem> + <para>The selection rectangle can't be changed because the + pad is currently busy. This can be caused, for instance, by + an active video stream on the pad. The ioctl must not be + retried without performing another action to fix the problem + first. Only returned by + <constant>VIDIOC_SUBDEV_S_SELECTION</constant></para> + </listitem> + </varlistentry> + <varlistentry> + <term><errorcode>EINVAL</errorcode></term> + <listitem> + <para>The &v4l2-subdev-selection; + <structfield>pad</structfield> references a non-existing + pad, the <structfield>which</structfield> field references a + non-existing format, or the selection target is not + supported on the given subdev pad.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> +</refentry> diff --git a/MAINTAINERS b/MAINTAINERS index b0f1073c40b0..860bc6117851 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2696,6 +2696,13 @@ S: Maintained F: Documentation/hwmon/f71805f F: drivers/hwmon/f71805f.c +FC0011 TUNER DRIVER +M: Michael Buesch <m@bues.ch> +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/common/tuners/fc0011.h +F: drivers/media/common/tuners/fc0011.c + FANOTIFY M: Eric Paris <eparis@redhat.com> S: Maintained diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 4a6d5cef3964..0fd15d925e15 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -204,6 +204,13 @@ config MEDIA_TUNER_TDA18218 help NXP TDA18218 silicon tuner driver. +config MEDIA_TUNER_FC0011 + tristate "Fitipower FC0011 silicon tuner" + depends on VIDEO_MEDIA && I2C + default m if MEDIA_TUNER_CUSTOMISE + help + Fitipower FC0011 silicon tuner driver. + config MEDIA_TUNER_TDA18212 tristate "NXP TDA18212 silicon tuner" depends on VIDEO_MEDIA && I2C @@ -211,4 +218,10 @@ config MEDIA_TUNER_TDA18212 help NXP TDA18212 silicon tuner driver. +config MEDIA_TUNER_TUA9001 + tristate "Infineon TUA 9001 silicon tuner" + depends on VIDEO_MEDIA && I2C + default m if MEDIA_TUNER_CUSTOMISE + help + Infineon TUA 9001 silicon tuner driver. endmenu diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile index f80407eb8998..64ee06fa83f1 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/common/tuners/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o +obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o +obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb/frontends diff --git a/drivers/media/common/tuners/fc0011.c b/drivers/media/common/tuners/fc0011.c new file mode 100644 index 000000000000..e4882546c283 --- /dev/null +++ b/drivers/media/common/tuners/fc0011.c @@ -0,0 +1,524 @@ +/* + * Fitipower FC0011 tuner driver + * + * Copyright (C) 2012 Michael Buesch <m@bues.ch> + * + * Derived from FC0012 tuner driver: + * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "fc0011.h" + + +/* Tuner registers */ +enum { + FC11_REG_0, + FC11_REG_FA, /* FA */ + FC11_REG_FP, /* FP */ + FC11_REG_XINHI, /* XIN high 8 bit */ + FC11_REG_XINLO, /* XIN low 8 bit */ + FC11_REG_VCO, /* VCO */ + FC11_REG_VCOSEL, /* VCO select */ + FC11_REG_7, /* Unknown tuner reg 7 */ + FC11_REG_8, /* Unknown tuner reg 8 */ + FC11_REG_9, + FC11_REG_10, /* Unknown tuner reg 10 */ + FC11_REG_11, /* Unknown tuner reg 11 */ + FC11_REG_12, + FC11_REG_RCCAL, /* RC calibrate */ + FC11_REG_VCOCAL, /* VCO calibrate */ + FC11_REG_15, + FC11_REG_16, /* Unknown tuner reg 16 */ + FC11_REG_17, + + FC11_NR_REGS, /* Number of registers */ +}; + +enum FC11_REG_VCOSEL_bits { + FC11_VCOSEL_2 = 0x08, /* VCO select 2 */ + FC11_VCOSEL_1 = 0x10, /* VCO select 1 */ + FC11_VCOSEL_CLKOUT = 0x20, /* Fix clock out */ + FC11_VCOSEL_BW7M = 0x40, /* 7MHz bw */ + FC11_VCOSEL_BW6M = 0x80, /* 6MHz bw */ +}; + +enum FC11_REG_RCCAL_bits { + FC11_RCCAL_FORCE = 0x10, /* force */ +}; + +enum FC11_REG_VCOCAL_bits { + FC11_VCOCAL_RUN = 0, /* VCO calibration run */ + FC11_VCOCAL_VALUEMASK = 0x3F, /* VCO calibration value mask */ + FC11_VCOCAL_OK = 0x40, /* VCO calibration Ok */ + FC11_VCOCAL_RESET = 0x80, /* VCO calibration reset */ +}; + + +struct fc0011_priv { + struct i2c_adapter *i2c; + u8 addr; + + u32 frequency; + u32 bandwidth; +}; + + +static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val) +{ + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { .addr = priv->addr, + .flags = 0, .buf = buf, .len = 2 }; + + if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + dev_err(&priv->i2c->dev, + "I2C write reg failed, reg: %02x, val: %02x\n", + reg, val); + return -EIO; + } + + return 0; +} + +static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val) +{ + u8 dummy; + struct i2c_msg msg[2] = { + { .addr = priv->addr, + .flags = 0, .buf = ®, .len = 1 }, + { .addr = priv->addr, + .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 }, + }; + + if (i2c_transfer(priv->i2c, msg, 2) != 2) { + dev_err(&priv->i2c->dev, + "I2C read failed, reg: %02x\n", reg); + return -EIO; + } + + return 0; +} + +static int fc0011_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + + return 0; +} + +static int fc0011_init(struct dvb_frontend *fe) +{ + struct fc0011_priv *priv = fe->tuner_priv; + int err; + + if (WARN_ON(!fe->callback)) + return -EINVAL; + + err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + FC0011_FE_CALLBACK_POWER, priv->addr); + if (err) { + dev_err(&priv->i2c->dev, "Power-on callback failed\n"); + return err; + } + err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + FC0011_FE_CALLBACK_RESET, priv->addr); + if (err) { + dev_err(&priv->i2c->dev, "Reset callback failed\n"); + return err; + } + + return 0; +} + +/* Initiate VCO calibration */ +static int fc0011_vcocal_trigger(struct fc0011_priv *priv) +{ + int err; + + err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET); + if (err) + return err; + err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); + if (err) + return err; + + return 0; +} + +/* Read VCO calibration value */ +static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value) +{ + int err; + + err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN); + if (err) + return err; + usleep_range(10000, 20000); + err = fc0011_readreg(priv, FC11_REG_VCOCAL, value); + if (err) + return err; + + return 0; +} + +static int fc0011_set_params(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + struct fc0011_priv *priv = fe->tuner_priv; + int err; + unsigned int i, vco_retries; + u32 freq = p->frequency / 1000; + u32 bandwidth = p->bandwidth_hz / 1000; + u32 fvco, xin, xdiv, xdivr; + u16 frac; + u8 fa, fp, vco_sel, vco_cal; + u8 regs[FC11_NR_REGS] = { }; + + regs[FC11_REG_7] = 0x0F; + regs[FC11_REG_8] = 0x3E; + regs[FC11_REG_10] = 0xB8; + regs[FC11_REG_11] = 0x80; + regs[FC11_REG_RCCAL] = 0x04; + err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); + err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); + err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); + err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); + err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); + if (err) + return -EIO; + + /* Set VCO freq and VCO div */ + if (freq < 54000) { + fvco = freq * 64; + regs[FC11_REG_VCO] = 0x82; + } else if (freq < 108000) { + fvco = freq * 32; + regs[FC11_REG_VCO] = 0x42; + } else if (freq < 216000) { + fvco = freq * 16; + regs[FC11_REG_VCO] = 0x22; + } else if (freq < 432000) { + fvco = freq * 8; + regs[FC11_REG_VCO] = 0x12; + } else { + fvco = freq * 4; + regs[FC11_REG_VCO] = 0x0A; + } + + /* Calc XIN. The PLL reference frequency is 18 MHz. */ + xdiv = fvco / 18000; + frac = fvco - xdiv * 18000; + frac = (frac << 15) / 18000; + if (frac >= 16384) + frac += 32786; + if (!frac) + xin = 0; + else if (frac < 511) + xin = 512; + else if (frac < 65026) + xin = frac; + else + xin = 65024; + regs[FC11_REG_XINHI] = xin >> 8; + regs[FC11_REG_XINLO] = xin; + + /* Calc FP and FA */ + xdivr = xdiv; + if (fvco - xdiv * 18000 >= 9000) + xdivr += 1; /* round */ + fp = xdivr / 8; + fa = xdivr - fp * 8; + if (fa < 2) { + fp -= 1; + fa += 8; + } + if (fp > 0x1F) { + fp &= 0x1F; + fa &= 0xF; + } + if (fa >= fp) { + dev_warn(&priv->i2c->dev, + "fa %02X >= fp %02X, but trying to continue\n", + (unsigned int)(u8)fa, (unsigned int)(u8)fp); + } + regs[FC11_REG_FA] = fa; + regs[FC11_REG_FP] = fp; + + /* Select bandwidth */ + switch (bandwidth) { + case 8000: + break; + case 7000: + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M; + break; + default: + dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. " + "Using 6000 kHz.\n", + bandwidth); + bandwidth = 6000; + /* fallthrough */ + case 6000: + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M; + break; + } + + /* Pre VCO select */ + if (fvco < 2320000) { + vco_sel = 0; + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + } else if (fvco < 3080000) { + vco_sel = 1; + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; + } else { + vco_sel = 2; + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; + } + + /* Fix for low freqs */ + if (freq < 45000) { + regs[FC11_REG_FA] = 0x6; + regs[FC11_REG_FP] = 0x11; + } + + /* Clock out fix */ + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT; + + /* Write the cached registers */ + for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) { + err = fc0011_writereg(priv, i, regs[i]); + if (err) + return err; + } + + /* VCO calibration */ + err = fc0011_vcocal_trigger(priv); + if (err) + return err; + err = fc0011_vcocal_read(priv, &vco_cal); + if (err) + return err; + vco_retries = 0; + while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) { + /* Reset the tuner and try again */ + err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, + FC0011_FE_CALLBACK_RESET, priv->addr); + if (err) { + dev_err(&priv->i2c->dev, "Failed to reset tuner\n"); + return err; + } + /* Reinit tuner config */ + err = 0; + for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) + err |= fc0011_writereg(priv, i, regs[i]); + err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]); + err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]); + err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]); + err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]); + err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); + if (err) + return -EIO; + /* VCO calibration */ + err = fc0011_vcocal_trigger(priv); + if (err) + return err; + err = fc0011_vcocal_read(priv, &vco_cal); + if (err) + return err; + vco_retries++; + } + if (!(vco_cal & FC11_VCOCAL_OK)) { + dev_err(&priv->i2c->dev, + "Failed to read VCO calibration value (got %02X)\n", + (unsigned int)vco_cal); + return -EIO; + } + vco_cal &= FC11_VCOCAL_VALUEMASK; + + switch (vco_sel) { + case 0: + if (vco_cal < 8) { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + err = fc0011_vcocal_trigger(priv); + if (err) + return err; + } else { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + } + break; + case 1: + if (vco_cal < 5) { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + err = fc0011_vcocal_trigger(priv); + if (err) + return err; + } else if (vco_cal <= 48) { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + } else { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + err = fc0011_vcocal_trigger(priv); + if (err) + return err; + } + break; + case 2: + if (vco_cal > 53) { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1; + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + err = fc0011_vcocal_trigger(priv); + if (err) + return err; + } else { + regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); + regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2; + err = fc0011_writereg(priv, FC11_REG_VCOSEL, + regs[FC11_REG_VCOSEL]); + if (err) + return err; + } + break; + } + err = fc0011_vcocal_read(priv, NULL); + if (err) + return err; + usleep_range(10000, 50000); + + err = fc0011_readreg(priv, FC11_REG_RCCAL, ®s[FC11_REG_RCCAL]); + if (err) + return err; + regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE; + err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]); + if (err) + return err; + err = fc0011_writereg(priv, FC11_REG_16, 0xB); + if (err) + return err; + + dev_dbg(&priv->i2c->dev, "Tuned to " + "fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X " + "vcocal=%02X(%u) bw=%u\n", + (unsigned int)regs[FC11_REG_FA], + (unsigned int)regs[FC11_REG_FP], + (unsigned int)regs[FC11_REG_XINHI], + (unsigned int)regs[FC11_REG_XINLO], + (unsigned int)regs[FC11_REG_VCO], + (unsigned int)regs[FC11_REG_VCOSEL], + (unsigned int)vco_cal, vco_retries, + (unsigned int)bandwidth); + + priv->frequency = p->frequency; + priv->bandwidth = p->bandwidth_hz; + + return 0; +} + +static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct fc0011_priv *priv = fe->tuner_priv; + + *frequency = priv->frequency; + + return 0; +} + +static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + *frequency = 0; + + return 0; +} + +static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct fc0011_priv *priv = fe->tuner_priv; + + *bandwidth = priv->bandwidth; + + return 0; +} + +static const struct dvb_tuner_ops fc0011_tuner_ops = { + .info = { + .name = "Fitipower FC0011", + + .frequency_min = 45000000, + .frequency_max = 1000000000, + }, + + .release = fc0011_release, + .init = fc0011_init, + + .set_params = fc0011_set_params, + + .get_frequency = fc0011_get_frequency, + .get_if_frequency = fc0011_get_if_frequency, + .get_bandwidth = fc0011_get_bandwidth, +}; + +struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct fc0011_config *config) +{ + struct fc0011_priv *priv; + + priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL); + if (!priv) + return NULL; + + priv->i2c = i2c; + priv->addr = config->i2c_address; + + fe->tuner_priv = priv; + fe->ops.tuner_ops = fc0011_tuner_ops; + + dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n"); + + return fe; +} +EXPORT_SYMBOL(fc0011_attach); + +MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver"); +MODULE_AUTHOR("Michael Buesch <m@bues.ch>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/fc0011.h b/drivers/media/common/tuners/fc0011.h new file mode 100644 index 000000000000..0ee581f122d2 --- /dev/null +++ b/drivers/media/common/tuners/fc0011.h @@ -0,0 +1,41 @@ +#ifndef LINUX_FC0011_H_ +#define LINUX_FC0011_H_ + +#include "dvb_frontend.h" + + +/** struct fc0011_config - fc0011 hardware config + * + * @i2c_address: I2C bus address. + */ +struct fc0011_config { + u8 i2c_address; +}; + +/** enum fc0011_fe_callback_commands - Frontend callbacks + * + * @FC0011_FE_CALLBACK_POWER: Power on tuner hardware. + * @FC0011_FE_CALLBACK_RESET: Request a tuner reset. + */ +enum fc0011_fe_callback_commands { + FC0011_FE_CALLBACK_POWER, + FC0011_FE_CALLBACK_RESET, +}; + +#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\ + defined(CONFIG_MEDIA_TUNER_FC0011_MODULE) +struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct fc0011_config *config); +#else +static inline +struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + const struct fc0011_config *config) +{ + dev_err(&i2c->dev, "fc0011 driver disabled in Kconfig\n"); + return NULL; +} +#endif + +#endif /* LINUX_FC0011_H_ */ diff --git a/drivers/media/common/tuners/tua9001.c b/drivers/media/common/tuners/tua9001.c new file mode 100644 index 000000000000..de2607084672 --- /dev/null +++ b/drivers/media/common/tuners/tua9001.c @@ -0,0 +1,215 @@ +/* + * Infineon TUA 9001 silicon tuner driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "tua9001.h" +#include "tua9001_priv.h" + +/* write register */ +static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) +{ + int ret; + u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff }; + struct i2c_msg msg[1] = { + { + .addr = priv->cfg->i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + ret = i2c_transfer(priv->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n", + __func__, ret, reg); + ret = -EREMOTEIO; + } + + return ret; +} + +static int tua9001_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + + return 0; +} + +static int tua9001_init(struct dvb_frontend *fe) +{ + struct tua9001_priv *priv = fe->tuner_priv; + int ret = 0; + u8 i; + struct reg_val data[] = { + { 0x1e, 0x6512 }, + { 0x25, 0xb888 }, + { 0x39, 0x5460 }, + { 0x3b, 0x00c0 }, + { 0x3a, 0xf000 }, + { 0x08, 0x0000 }, + { 0x32, 0x0030 }, + { 0x41, 0x703a }, + { 0x40, 0x1c78 }, + { 0x2c, 0x1c00 }, + { 0x36, 0xc013 }, + { 0x37, 0x6f18 }, + { 0x27, 0x0008 }, + { 0x2a, 0x0001 }, + { 0x34, 0x0a40 }, + }; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ + + for (i = 0; i < ARRAY_SIZE(data); i++) { + ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); + if (ret) + break; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ + + if (ret < 0) + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int tua9001_set_params(struct dvb_frontend *fe) +{ + struct tua9001_priv *priv = fe->tuner_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i; + u16 val; + u32 frequency; + struct reg_val data[2]; + + pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", + __func__, c->delivery_system, c->frequency, + c->bandwidth_hz); + + switch (c->delivery_system) { + case SYS_DVBT: + switch (c->bandwidth_hz) { + case 8000000: + val = 0x0000; + break; + case 7000000: + val = 0x1000; + break; + case 6000000: + val = 0x2000; + break; + case 5000000: + val = 0x3000; + break; + default: + ret = -EINVAL; + goto err; + } + break; + default: + ret = -EINVAL; + goto err; + } + + data[0].reg = 0x04; + data[0].val = val; + + frequency = (c->frequency - 150000000); + frequency /= 100; + frequency *= 48; + frequency /= 10000; + + data[1].reg = 0x1f; + data[1].val = frequency; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ + + for (i = 0; i < ARRAY_SIZE(data); i++) { + ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); + if (ret < 0) + break; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ + +err: + if (ret < 0) + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + *frequency = 0; /* Zero-IF */ + + return 0; +} + +static const struct dvb_tuner_ops tua9001_tuner_ops = { + .info = { + .name = "Infineon TUA 9001", + + .frequency_min = 170000000, + .frequency_max = 862000000, + .frequency_step = 0, + }, + + .release = tua9001_release, + + .init = tua9001_init, + .set_params = tua9001_set_params, + + .get_if_frequency = tua9001_get_if_frequency, +}; + +struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct tua9001_config *cfg) +{ + struct tua9001_priv *priv = NULL; + + priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); + if (priv == NULL) + return NULL; + + priv->cfg = cfg; + priv->i2c = i2c; + + printk(KERN_INFO "Infineon TUA 9001 successfully attached."); + + memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, + sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + return fe; +} +EXPORT_SYMBOL(tua9001_attach); + +MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver"); +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/tua9001.h b/drivers/media/common/tuners/tua9001.h new file mode 100644 index 000000000000..38d6ae76b1d6 --- /dev/null +++ b/drivers/media/common/tuners/tua9001.h @@ -0,0 +1,46 @@ +/* + * Infineon TUA 9001 silicon tuner driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef TUA9001_H +#define TUA9001_H + +#include "dvb_frontend.h" + +struct tua9001_config { + /* + * I2C address + */ + u8 i2c_addr; +}; + +#if defined(CONFIG_MEDIA_TUNER_TUA9001) || \ + (defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE)) +extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct tua9001_config *cfg); +#else +static inline struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, struct tua9001_config *cfg) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif diff --git a/drivers/media/common/tuners/tua9001_priv.h b/drivers/media/common/tuners/tua9001_priv.h new file mode 100644 index 000000000000..73cc1ce0575c --- /dev/null +++ b/drivers/media/common/tuners/tua9001_priv.h @@ -0,0 +1,34 @@ +/* + * Infineon TUA 9001 silicon tuner driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef TUA9001_PRIV_H +#define TUA9001_PRIV_H + +struct reg_val { + u8 reg; + u16 val; +}; + +struct tua9001_priv { + struct tua9001_config *cfg; + struct i2c_adapter *i2c; +}; + +#endif diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 63bf45679f98..be1db75091ff 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -422,3 +422,15 @@ config DVB_USB_RTL28XXU select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE help Say Y here to support the Realtek RTL28xxU DVB USB receiver. + +config DVB_USB_AF9035 + tristate "Afatech AF9035 DVB-T USB2.0 support" + depends on DVB_USB + select DVB_AF9033 + select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE + select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE + help + Say Y here to support the Afatech AF9035 based DVB USB receiver. + diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index b76acb5387e6..b667ac39a4e3 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile @@ -110,6 +110,9 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o dvb-usb-rtl28xxu-objs = rtl28xxu.o obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o +dvb-usb-af9035-objs = af9035.o +obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o + ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/ # due to tuner-xc3028 diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/dvb/dvb-usb/af9035.c new file mode 100644 index 000000000000..e1d6e6efa77b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9035.c @@ -0,0 +1,1164 @@ +/* + * Afatech AF9035 DVB USB driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "af9035.h" +#include "af9033.h" +#include "tua9001.h" +#include "fc0011.h" +#include "mxl5007t.h" +#include "tda18218.h" + +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +static DEFINE_MUTEX(af9035_usb_mutex); +static struct config af9035_config; +static struct dvb_usb_device_properties af9035_properties[2]; +static int af9035_properties_count = ARRAY_SIZE(af9035_properties); +static struct af9033_config af9035_af9033_config[] = { + { + .ts_mode = AF9033_TS_MODE_USB, + }, { + .ts_mode = AF9033_TS_MODE_SERIAL, + } +}; + +static u16 af9035_checksum(const u8 *buf, size_t len) +{ + size_t i; + u16 checksum = 0; + + for (i = 1; i < len; i++) { + if (i % 2) + checksum += buf[i] << 8; + else + checksum += buf[i]; + } + checksum = ~checksum; + + return checksum; +} + +static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) +{ +#define BUF_LEN 63 +#define REQ_HDR_LEN 4 /* send header size */ +#define ACK_HDR_LEN 3 /* rece header size */ +#define CHECKSUM_LEN 2 +#define USB_TIMEOUT 2000 + + int ret, act_len; + u8 buf[BUF_LEN]; + u32 msg_len; + static u8 seq; /* packet sequence number */ + u16 checksum, tmpsum; + + /* buffer overflow check */ + if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || + req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) { + pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__, + req->wlen, req->rlen); + return -EINVAL; + } + + if (mutex_lock_interruptible(&af9035_usb_mutex) < 0) + return -EAGAIN; + + buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1; + buf[1] = req->mbox; + buf[2] = req->cmd; + buf[3] = seq++; + if (req->wlen) + memcpy(&buf[4], req->wbuf, req->wlen); + + /* calc and add checksum */ + checksum = af9035_checksum(buf, buf[0] - 1); + buf[buf[0]-1] = (checksum >> 8); + buf[buf[0]-0] = (checksum & 0xff); + + msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ; + + /* send req */ + ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len, + &act_len, USB_TIMEOUT); + if (ret < 0) + err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len); + else + if (act_len != msg_len) + ret = -EIO; /* all data is not send */ + if (ret < 0) + goto err_mutex_unlock; + + /* no ack for those packets */ + if (req->cmd == CMD_FW_DL) + goto exit_mutex_unlock; + + /* receive ack and data if read req */ + msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN; + ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len, + &act_len, USB_TIMEOUT); + if (ret < 0) { + err("recv bulk message failed=%d", ret); + ret = -EIO; + goto err_mutex_unlock; + } + if (act_len != msg_len) { + err("recv bulk message truncated (%d != %u)\n", + act_len, (unsigned int)msg_len); + ret = -EIO; + goto err_mutex_unlock; + } + + /* verify checksum */ + checksum = af9035_checksum(buf, act_len - 2); + tmpsum = (buf[act_len - 2] << 8) | buf[act_len - 1]; + if (tmpsum != checksum) { + err("%s: command=%02X checksum mismatch (%04X != %04X)\n", + __func__, req->cmd, + (unsigned int)tmpsum, (unsigned int)checksum); + ret = -EIO; + goto err_mutex_unlock; + } + /* check status */ + if (buf[2]) { + pr_debug("%s: command=%02x failed fw error=%d\n", __func__, + req->cmd, buf[2]); + ret = -EIO; + goto err_mutex_unlock; + } + + /* read request, copy returned data to return buf */ + if (req->rlen) + memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen); + +err_mutex_unlock: +exit_mutex_unlock: + mutex_unlock(&af9035_usb_mutex); + + return ret; +} + +/* write multiple registers */ +static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) +{ + u8 wbuf[6 + len]; + u8 mbox = (reg >> 16) & 0xff; + struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL }; + + wbuf[0] = len; + wbuf[1] = 2; + wbuf[2] = 0; + wbuf[3] = 0; + wbuf[4] = (reg >> 8) & 0xff; + wbuf[5] = (reg >> 0) & 0xff; + memcpy(&wbuf[6], val, len); + + return af9035_ctrl_msg(d->udev, &req); +} + +/* read multiple registers */ +static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len) +{ + u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff }; + u8 mbox = (reg >> 16) & 0xff; + struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val }; + + return af9035_ctrl_msg(d->udev, &req); +} + +/* write single register */ +static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val) +{ + return af9035_wr_regs(d, reg, &val, 1); +} + +/* read single register */ +static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val) +{ + return af9035_rd_regs(d, reg, val, 1); +} + +/* write single register with mask */ +static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val, + u8 mask) +{ + int ret; + u8 tmp; + + /* no need for read if whole reg is written */ + if (mask != 0xff) { + ret = af9035_rd_regs(d, reg, &tmp, 1); + if (ret) + return ret; + + val &= mask; + tmp &= ~mask; + val |= tmp; + } + + return af9035_wr_regs(d, reg, &val, 1); +} + +static int af9035_i2c_master_xfer(struct i2c_adapter *adap, + struct i2c_msg msg[], int num) +{ + struct dvb_usb_device *d = i2c_get_adapdata(adap); + int ret; + + if (mutex_lock_interruptible(&d->i2c_mutex) < 0) + return -EAGAIN; + + /* + * I2C sub header is 5 bytes long. Meaning of those bytes are: + * 0: data len + * 1: I2C addr << 1 + * 2: reg addr len + * byte 3 and 4 can be used as reg addr + * 3: reg addr MSB + * used when reg addr len is set to 2 + * 4: reg addr LSB + * used when reg addr len is set to 1 or 2 + * + * For the simplify we do not use register addr at all. + * NOTE: As a firmware knows tuner type there is very small possibility + * there could be some tuner I2C hacks done by firmware and this may + * lead problems if firmware expects those bytes are used. + */ + if (num == 2 && !(msg[0].flags & I2C_M_RD) && + (msg[1].flags & I2C_M_RD)) { + if (msg[0].len > 40 || msg[1].len > 40) { + /* TODO: correct limits > 40 */ + ret = -EOPNOTSUPP; + } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { + /* integrated demod */ + u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | + msg[0].buf[2]; + ret = af9035_rd_regs(d, reg, &msg[1].buf[0], + msg[1].len); + } else { + /* I2C */ + u8 buf[5 + msg[0].len]; + struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), + buf, msg[1].len, msg[1].buf }; + buf[0] = msg[1].len; + buf[1] = msg[0].addr << 1; + buf[2] = 0x00; /* reg addr len */ + buf[3] = 0x00; /* reg addr MSB */ + buf[4] = 0x00; /* reg addr LSB */ + memcpy(&buf[5], msg[0].buf, msg[0].len); + ret = af9035_ctrl_msg(d->udev, &req); + } + } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { + if (msg[0].len > 40) { + /* TODO: correct limits > 40 */ + ret = -EOPNOTSUPP; + } else if (msg[0].addr == af9035_af9033_config[0].i2c_addr) { + /* integrated demod */ + u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 | + msg[0].buf[2]; + ret = af9035_wr_regs(d, reg, &msg[0].buf[3], + msg[0].len - 3); + } else { + /* I2C */ + u8 buf[5 + msg[0].len]; + struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, + 0, NULL }; + buf[0] = msg[0].len; + buf[1] = msg[0].addr << 1; + buf[2] = 0x00; /* reg addr len */ + buf[3] = 0x00; /* reg addr MSB */ + buf[4] = 0x00; /* reg addr LSB */ + memcpy(&buf[5], msg[0].buf, msg[0].len); + ret = af9035_ctrl_msg(d->udev, &req); + } + } else { + /* + * We support only two kind of I2C transactions: + * 1) 1 x read + 1 x write + * 2) 1 x write + */ + ret = -EOPNOTSUPP; + } + + mutex_unlock(&d->i2c_mutex); + + if (ret < 0) + return ret; + else + return num; +} + +static u32 af9035_i2c_functionality(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C; +} + +static struct i2c_algorithm af9035_i2c_algo = { + .master_xfer = af9035_i2c_master_xfer, + .functionality = af9035_i2c_functionality, +}; + +static int af9035_init(struct dvb_usb_device *d) +{ + int ret, i; + u16 frame_size = 87 * 188 / 4; + u8 packet_size = 512 / 4; + struct reg_val_mask tab[] = { + { 0x80f99d, 0x01, 0x01 }, + { 0x80f9a4, 0x01, 0x01 }, + { 0x00dd11, 0x00, 0x20 }, + { 0x00dd11, 0x00, 0x40 }, + { 0x00dd13, 0x00, 0x20 }, + { 0x00dd13, 0x00, 0x40 }, + { 0x00dd11, 0x20, 0x20 }, + { 0x00dd88, (frame_size >> 0) & 0xff, 0xff}, + { 0x00dd89, (frame_size >> 8) & 0xff, 0xff}, + { 0x00dd0c, packet_size, 0xff}, + { 0x00dd11, af9035_config.dual_mode << 6, 0x40 }, + { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff}, + { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff}, + { 0x00dd0d, packet_size, 0xff }, + { 0x80f9a3, 0x00, 0x01 }, + { 0x80f9cd, 0x00, 0x01 }, + { 0x80f99d, 0x00, 0x01 }, + { 0x80f9a4, 0x00, 0x01 }, + }; + + pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n", + __func__, d->udev->speed, frame_size, packet_size); + + /* init endpoints */ + for (i = 0; i < ARRAY_SIZE(tab); i++) { + ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val, + tab[i].mask); + if (ret < 0) + goto err; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_identify_state(struct usb_device *udev, + struct dvb_usb_device_properties *props, + struct dvb_usb_device_description **desc, + int *cold) +{ + int ret; + u8 wbuf[1] = { 1 }; + u8 rbuf[4]; + struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, + sizeof(rbuf), rbuf }; + + ret = af9035_ctrl_msg(udev, &req); + if (ret < 0) + goto err; + + pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__, + rbuf[0], rbuf[1], rbuf[2], rbuf[3]); + if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3]) + *cold = 0; + else + *cold = 1; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_download_firmware(struct usb_device *udev, + const struct firmware *fw) +{ + int ret, i, j, len; + u8 wbuf[1]; + u8 rbuf[4]; + struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; + struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL }; + struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; + u8 hdr_core; + u16 hdr_addr, hdr_data_len, hdr_checksum; + #define MAX_DATA 57 + #define HDR_SIZE 7 + + /* + * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info! + * + * byte 0: MCS 51 core + * There are two inside the AF9035 (1=Link and 2=OFDM) with separate + * address spaces + * byte 1-2: Big endian destination address + * byte 3-4: Big endian number of data bytes following the header + * byte 5-6: Big endian header checksum, apparently ignored by the chip + * Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256) + */ + + for (i = fw->size; i > HDR_SIZE;) { + hdr_core = fw->data[fw->size - i + 0]; + hdr_addr = fw->data[fw->size - i + 1] << 8; + hdr_addr |= fw->data[fw->size - i + 2] << 0; + hdr_data_len = fw->data[fw->size - i + 3] << 8; + hdr_data_len |= fw->data[fw->size - i + 4] << 0; + hdr_checksum = fw->data[fw->size - i + 5] << 8; + hdr_checksum |= fw->data[fw->size - i + 6] << 0; + + pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n", + __func__, hdr_core, hdr_addr, hdr_data_len, + hdr_checksum); + + if (((hdr_core != 1) && (hdr_core != 2)) || + (hdr_data_len > i)) { + pr_debug("%s: bad firmware\n", __func__); + break; + } + + /* download begin packet */ + req.cmd = CMD_FW_DL_BEGIN; + ret = af9035_ctrl_msg(udev, &req); + if (ret < 0) + goto err; + + /* download firmware packet(s) */ + for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) { + len = j; + if (len > MAX_DATA) + len = MAX_DATA; + req_fw_dl.wlen = len; + req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i + + HDR_SIZE + hdr_data_len - j]; + ret = af9035_ctrl_msg(udev, &req_fw_dl); + if (ret < 0) + goto err; + } + + /* download end packet */ + req.cmd = CMD_FW_DL_END; + ret = af9035_ctrl_msg(udev, &req); + if (ret < 0) + goto err; + + i -= hdr_data_len + HDR_SIZE; + + pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i); + } + + /* firmware loaded, request boot */ + req.cmd = CMD_FW_BOOT; + ret = af9035_ctrl_msg(udev, &req); + if (ret < 0) + goto err; + + /* ensure firmware starts */ + wbuf[0] = 1; + ret = af9035_ctrl_msg(udev, &req_fw_ver); + if (ret < 0) + goto err; + + if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { + info("firmware did not run"); + ret = -ENODEV; + goto err; + } + + info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], + rbuf[3]); + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_download_firmware_it9135(struct usb_device *udev, + const struct firmware *fw) +{ + int ret, i, i_prev; + u8 wbuf[1]; + u8 rbuf[4]; + struct usb_req req = { 0, 0, 0, NULL, 0, NULL }; + struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL }; + struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ; + #define HDR_SIZE 7 + + /* + * There seems to be following firmware header. Meaning of bytes 0-3 + * is unknown. + * + * 0: 3 + * 1: 0, 1 + * 2: 0 + * 3: 1, 2, 3 + * 4: addr MSB + * 5: addr LSB + * 6: count of data bytes ? + */ + + for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) { + if (i == fw->size || + (fw->data[i + 0] == 0x03 && + (fw->data[i + 1] == 0x00 || + fw->data[i + 1] == 0x01) && + fw->data[i + 2] == 0x00)) { + req_fw_dl.wlen = i - i_prev; + req_fw_dl.wbuf = (u8 *) &fw->data[i_prev]; + i_prev = i; + ret = af9035_ctrl_msg(udev, &req_fw_dl); + if (ret < 0) + goto err; + + pr_debug("%s: data uploaded=%d\n", __func__, i); + } + } + + /* firmware loaded, request boot */ + req.cmd = CMD_FW_BOOT; + ret = af9035_ctrl_msg(udev, &req); + if (ret < 0) + goto err; + + /* ensure firmware starts */ + wbuf[0] = 1; + ret = af9035_ctrl_msg(udev, &req_fw_ver); + if (ret < 0) + goto err; + + if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) { + info("firmware did not run"); + ret = -ENODEV; + goto err; + } + + info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2], + rbuf[3]); + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +/* abuse that callback as there is no better one for reading eeprom */ +static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) +{ + int ret, i, eeprom_shift = 0; + u8 tmp; + u16 tmp16; + + /* check if there is dual tuners */ + ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp); + if (ret < 0) + goto err; + + af9035_config.dual_mode = tmp; + pr_debug("%s: dual mode=%d\n", __func__, af9035_config.dual_mode); + + for (i = 0; i < af9035_properties[0].num_adapters; i++) { + /* tuner */ + ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp); + if (ret < 0) + goto err; + + af9035_af9033_config[i].tuner = tmp; + pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp); + + switch (tmp) { + case AF9033_TUNER_TUA9001: + case AF9033_TUNER_FC0011: + case AF9033_TUNER_MXL5007T: + case AF9033_TUNER_TDA18218: + af9035_af9033_config[i].spec_inv = 1; + break; + default: + af9035_config.hw_not_supported = true; + warn("tuner ID=%02x not supported, please report!", + tmp); + }; + + /* tuner IF frequency */ + ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp); + if (ret < 0) + goto err; + + tmp16 = tmp; + + ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp); + if (ret < 0) + goto err; + + tmp16 |= tmp << 8; + + pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16); + + eeprom_shift = 0x10; /* shift for the 2nd tuner params */ + } + + /* get demod clock */ + ret = af9035_rd_reg(d, 0x00d800, &tmp); + if (ret < 0) + goto err; + + tmp = (tmp >> 0) & 0x0f; + + for (i = 0; i < af9035_properties[0].num_adapters; i++) + af9035_af9033_config[i].clock = clock_lut[tmp]; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +/* abuse that callback as there is no better one for reading eeprom */ +static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6]) +{ + int ret, i; + u8 tmp; + + af9035_config.dual_mode = 0; + + /* get demod clock */ + ret = af9035_rd_reg(d, 0x00d800, &tmp); + if (ret < 0) + goto err; + + tmp = (tmp >> 0) & 0x0f; + + for (i = 0; i < af9035_properties[0].num_adapters; i++) + af9035_af9033_config[i].clock = clock_lut_it9135[tmp]; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d, + int cmd, int arg) +{ + int ret; + + switch (cmd) { + case FC0011_FE_CALLBACK_POWER: + /* Tuner enable */ + ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1); + if (ret < 0) + goto err; + + /* LED */ + ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1); + if (ret < 0) + goto err; + + usleep_range(10000, 50000); + break; + case FC0011_FE_CALLBACK_RESET: + ret = af9035_wr_reg(d, 0xd8e9, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0xd8e8, 1); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(d, 0xd8e7, 1); + if (ret < 0) + goto err; + + usleep_range(10000, 20000); + + ret = af9035_wr_reg(d, 0xd8e7, 0); + if (ret < 0) + goto err; + + usleep_range(10000, 20000); + break; + default: + ret = -EINVAL; + goto err; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg) +{ + switch (af9035_af9033_config[0].tuner) { + case AF9033_TUNER_FC0011: + return af9035_fc0011_tuner_callback(d, cmd, arg); + default: + break; + } + + return -ENODEV; +} + +static int af9035_frontend_callback(void *adapter_priv, int component, + int cmd, int arg) +{ + struct i2c_adapter *adap = adapter_priv; + struct dvb_usb_device *d = i2c_get_adapdata(adap); + + switch (component) { + case DVB_FRONTEND_COMPONENT_TUNER: + return af9035_tuner_callback(d, cmd, arg); + default: + break; + } + + return -EINVAL; +} + +static int af9035_frontend_attach(struct dvb_usb_adapter *adap) +{ + int ret; + + if (af9035_config.hw_not_supported) { + ret = -ENODEV; + goto err; + } + + if (adap->id == 0) { + ret = af9035_wr_reg(adap->dev, 0x00417f, + af9035_af9033_config[1].i2c_addr); + if (ret < 0) + goto err; + + ret = af9035_wr_reg(adap->dev, 0x00d81a, + af9035_config.dual_mode); + if (ret < 0) + goto err; + } + + /* attach demodulator */ + adap->fe_adap[0].fe = dvb_attach(af9033_attach, + &af9035_af9033_config[adap->id], &adap->dev->i2c_adap); + if (adap->fe_adap[0].fe == NULL) { + ret = -ENODEV; + goto err; + } + + /* disable I2C-gate */ + adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL; + adap->fe_adap[0].fe->callback = af9035_frontend_callback; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static struct tua9001_config af9035_tua9001_config = { + .i2c_addr = 0x60, +}; + +static const struct fc0011_config af9035_fc0011_config = { + .i2c_address = 0x60, +}; + +static struct mxl5007t_config af9035_mxl5007t_config = { + .xtal_freq_hz = MxL_XTAL_24_MHZ, + .if_freq_hz = MxL_IF_4_57_MHZ, + .invert_if = 0, + .loop_thru_enable = 0, + .clk_out_enable = 0, + .clk_out_amp = MxL_CLKOUT_AMP_0_94V, +}; + +static struct tda18218_config af9035_tda18218_config = { + .i2c_address = 0x60, + .i2c_wr_max = 21, +}; + +static int af9035_tuner_attach(struct dvb_usb_adapter *adap) +{ + int ret; + struct dvb_frontend *fe; + + switch (af9035_af9033_config[adap->id].tuner) { + case AF9033_TUNER_TUA9001: + /* AF9035 gpiot3 = TUA9001 RESETN + AF9035 gpiot2 = TUA9001 RXEN */ + + /* configure gpiot2 and gpiot2 as output */ + ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01); + if (ret < 0) + goto err; + + ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01); + if (ret < 0) + goto err; + + /* reset tuner */ + ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01); + if (ret < 0) + goto err; + + usleep_range(2000, 20000); + + ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01); + if (ret < 0) + goto err; + + /* activate tuner RX */ + /* TODO: use callback for TUA9001 RXEN */ + ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01); + if (ret < 0) + goto err; + + /* attach tuner */ + fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, &af9035_tua9001_config); + break; + case AF9033_TUNER_FC0011: + fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, &af9035_fc0011_config); + break; + case AF9033_TUNER_MXL5007T: + ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8df, 0); + if (ret < 0) + goto err; + + msleep(30); + + ret = af9035_wr_reg(adap->dev, 0x00d8df, 1); + if (ret < 0) + goto err; + + msleep(300); + + ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1); + if (ret < 0) + goto err; + ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1); + if (ret < 0) + goto err; + + /* attach tuner */ + fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config); + break; + case AF9033_TUNER_TDA18218: + /* attach tuner */ + fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe, + &adap->dev->i2c_adap, &af9035_tda18218_config); + break; + default: + fe = NULL; + } + + if (fe == NULL) { + ret = -ENODEV; + goto err; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +enum af9035_id_entry { + AF9035_15A4_9035, + AF9035_15A4_1001, + AF9035_0CCD_0093, + AF9035_07CA_A835, + AF9035_07CA_B835, + AF9035_07CA_1867, + AF9035_07CA_A867, + AF9035_07CA_0825, +}; + +static struct usb_device_id af9035_id[] = { + [AF9035_15A4_9035] = { + USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035)}, + [AF9035_15A4_1001] = { + USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_2)}, + [AF9035_0CCD_0093] = { + USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)}, + [AF9035_07CA_A835] = { + USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)}, + [AF9035_07CA_B835] = { + USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)}, + [AF9035_07CA_1867] = { + USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)}, + [AF9035_07CA_A867] = { + USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)}, + [AF9035_07CA_0825] = { + USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)}, + {}, +}; + +MODULE_DEVICE_TABLE(usb, af9035_id); + +static struct dvb_usb_device_properties af9035_properties[] = { + { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = af9035_download_firmware, + .firmware = "dvb-usb-af9035-02.fw", + .no_reconnect = 1, + + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = { + { + .frontend_attach = af9035_frontend_attach, + .tuner_attach = af9035_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x84, + .u = { + .bulk = { + .buffersize = (87 * 188), + } + } + } + } + } + } + }, + + .identify_state = af9035_identify_state, + .read_mac_address = af9035_read_mac_address, + + .i2c_algo = &af9035_i2c_algo, + + .num_device_descs = 5, + .devices = { + { + .name = "Afatech AF9035 reference design", + .cold_ids = { + &af9035_id[AF9035_15A4_9035], + &af9035_id[AF9035_15A4_1001], + }, + }, { + .name = "TerraTec Cinergy T Stick", + .cold_ids = { + &af9035_id[AF9035_0CCD_0093], + }, + }, { + .name = "AVerMedia AVerTV Volar HD/PRO (A835)", + .cold_ids = { + &af9035_id[AF9035_07CA_A835], + &af9035_id[AF9035_07CA_B835], + }, + }, { + .name = "AVerMedia HD Volar (A867)", + .cold_ids = { + &af9035_id[AF9035_07CA_1867], + &af9035_id[AF9035_07CA_A867], + }, + }, { + .name = "AVerMedia Twinstar (A825)", + .cold_ids = { + &af9035_id[AF9035_07CA_0825], + }, + }, + } + }, + { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = DEVICE_SPECIFIC, + .download_firmware = af9035_download_firmware_it9135, + .firmware = "dvb-usb-it9135-01.fw", + .no_reconnect = 1, + + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = { + { + .frontend_attach = af9035_frontend_attach, + .tuner_attach = af9035_tuner_attach, + .stream = { + .type = USB_BULK, + .count = 6, + .endpoint = 0x84, + .u = { + .bulk = { + .buffersize = (87 * 188), + } + } + } + } + } + } + }, + + .identify_state = af9035_identify_state, + .read_mac_address = af9035_read_mac_address_it9135, + + .i2c_algo = &af9035_i2c_algo, + + .num_device_descs = 0, /* disabled as no support for IT9135 */ + .devices = { + { + .name = "ITE Tech. IT9135 reference design", + }, + } + }, +}; + +static int af9035_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret, i; + struct dvb_usb_device *d = NULL; + struct usb_device *udev; + bool found; + + pr_debug("%s: interface=%d\n", __func__, + intf->cur_altsetting->desc.bInterfaceNumber); + + /* interface 0 is used by DVB-T receiver and + interface 1 is for remote controller (HID) */ + if (intf->cur_altsetting->desc.bInterfaceNumber != 0) + return 0; + + /* Dynamic USB ID support. Replaces first device ID with current one. */ + udev = interface_to_usbdev(intf); + + for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) { + if (af9035_id[i].idVendor == + le16_to_cpu(udev->descriptor.idVendor) && + af9035_id[i].idProduct == + le16_to_cpu(udev->descriptor.idProduct)) { + found = true; + break; + } + } + + if (!found) { + pr_debug("%s: using dynamic ID %04x:%04x\n", __func__, + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); + af9035_properties[0].devices[0].cold_ids[0]->idVendor = + le16_to_cpu(udev->descriptor.idVendor); + af9035_properties[0].devices[0].cold_ids[0]->idProduct = + le16_to_cpu(udev->descriptor.idProduct); + } + + + for (i = 0; i < af9035_properties_count; i++) { + ret = dvb_usb_device_init(intf, &af9035_properties[i], + THIS_MODULE, &d, adapter_nr); + + if (ret == -ENODEV) + continue; + else + break; + } + + if (ret < 0) + goto err; + + if (d) { + ret = af9035_init(d); + if (ret < 0) + goto err; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver af9035_usb_driver = { + .name = "dvb_usb_af9035", + .probe = af9035_usb_probe, + .disconnect = dvb_usb_device_exit, + .id_table = af9035_id, +}; + +module_usb_driver(af9035_usb_driver); + +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_DESCRIPTION("Afatech AF9035 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/af9035.h b/drivers/media/dvb/dvb-usb/af9035.h new file mode 100644 index 000000000000..031bd9cf0cb2 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/af9035.h @@ -0,0 +1,120 @@ +/* + * Afatech AF9035 DVB USB driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef AF9035_H +#define AF9035_H + +/* prefix for dvb-usb log writings */ +#define DVB_USB_LOG_PREFIX "af9035" + +#include "dvb-usb.h" + +struct reg_val { + u32 reg; + u8 val; +}; + +struct reg_val_mask { + u32 reg; + u8 val; + u8 mask; +}; + +struct usb_req { + u8 cmd; + u8 mbox; + u8 wlen; + u8 *wbuf; + u8 rlen; + u8 *rbuf; +}; + +struct config { + bool dual_mode; + bool hw_not_supported; +}; + +struct fw_segment { +#define SEGMENT_FW_DL 0 +#define SEGMENT_ROM_COPY 1 +#define SEGMENT_DIRECT_CMD 2 + u8 type; + u32 len; +}; + +struct fw_header { +#define SEGMENT_MAX_COUNT 6 + u8 segment_count; + struct fw_segment segment[SEGMENT_MAX_COUNT]; +}; + +u32 clock_lut[] = { + 20480000, /* FPGA */ + 16384000, /* 16.38 MHz */ + 20480000, /* 20.48 MHz */ + 36000000, /* 36.00 MHz */ + 30000000, /* 30.00 MHz */ + 26000000, /* 26.00 MHz */ + 28000000, /* 28.00 MHz */ + 32000000, /* 32.00 MHz */ + 34000000, /* 34.00 MHz */ + 24000000, /* 24.00 MHz */ + 22000000, /* 22.00 MHz */ + 12000000, /* 12.00 MHz */ +}; + +u32 clock_lut_it9135[] = { + 12000000, /* 12.00 MHz */ + 20480000, /* 20.48 MHz */ + 36000000, /* 36.00 MHz */ + 30000000, /* 30.00 MHz */ + 26000000, /* 26.00 MHz */ + 28000000, /* 28.00 MHz */ + 32000000, /* 32.00 MHz */ + 34000000, /* 34.00 MHz */ + 24000000, /* 24.00 MHz */ + 22000000, /* 22.00 MHz */ +}; + +/* EEPROM locations */ +#define EEPROM_IR_MODE 0x430d +#define EEPROM_DUAL_MODE 0x4326 +#define EEPROM_IR_TYPE 0x4329 +#define EEPROM_1_IFFREQ_L 0x432d +#define EEPROM_1_IFFREQ_H 0x432e +#define EEPROM_1_TUNER_ID 0x4331 +#define EEPROM_2_IFFREQ_L 0x433d +#define EEPROM_2_IFFREQ_H 0x433e +#define EEPROM_2_TUNER_ID 0x4341 + +/* USB commands */ +#define CMD_MEM_RD 0x00 +#define CMD_MEM_WR 0x01 +#define CMD_I2C_RD 0x02 +#define CMD_I2C_WR 0x03 +#define CMD_FW_DL 0x21 +#define CMD_FW_QUERYINFO 0x22 +#define CMD_FW_BOOT 0x23 +#define CMD_FW_DL_BEGIN 0x24 +#define CMD_FW_DL_END 0x25 +#define CMD_FW_SCATTER_WR 0x29 + +#endif diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 397d8f232731..94d3f8a5cd9e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -76,6 +76,8 @@ #define USB_PID_AFATECH_AF9005 0x9020 #define USB_PID_AFATECH_AF9015_9015 0x9015 #define USB_PID_AFATECH_AF9015_9016 0x9016 +#define USB_PID_AFATECH_AF9035 0x9035 +#define USB_PID_AFATECH_AF9035_2 0x1001 #define USB_PID_TREKSTOR_DVBT 0x901b #define USB_VID_ALINK_DTU 0xf170 #define USB_PID_ANSONIC_DVBT_USB 0x6000 @@ -152,6 +154,7 @@ #define USB_PID_KWORLD_VSTREAM_WARM 0x17df #define USB_PID_TERRATEC_CINERGY_T_USB_XE 0x0055 #define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2 0x0069 +#define USB_PID_TERRATEC_CINERGY_T_STICK 0x0093 #define USB_PID_TERRATEC_CINERGY_T_STICK_RC 0x0097 #define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC 0x0099 #define USB_PID_TWINHAN_VP7041_COLD 0x3201 @@ -221,6 +224,11 @@ #define USB_PID_AVERMEDIA_A850T 0x850b #define USB_PID_AVERMEDIA_A805 0xa805 #define USB_PID_AVERMEDIA_A815M 0x815a +#define USB_PID_AVERMEDIA_A835 0xa835 +#define USB_PID_AVERMEDIA_B835 0xb835 +#define USB_PID_AVERMEDIA_1867 0x1867 +#define USB_PID_AVERMEDIA_A867 0xa867 +#define USB_PID_AVERMEDIA_TWINSTAR 0x0825 #define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c index 81305de2fea5..91834c583580 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf.c @@ -340,7 +340,6 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) struct mxl111sf_state *state = d->priv; struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv; int ret = 0; - u8 tmp; deb_info("%s(%d)\n", __func__, onoff); diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 21246707fbfb..e11adb64e9e6 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -713,6 +713,11 @@ config DVB_M88RS2000 A DVB-S tuner module. Say Y when you want to support this frontend. +config DVB_AF9033 + tristate "Afatech AF9033 DVB-T demodulator" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 86fa808bf589..6ca75578ecac 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -98,4 +98,5 @@ obj-$(CONFIG_DVB_A8293) += a8293.o obj-$(CONFIG_DVB_TDA10071) += tda10071.o obj-$(CONFIG_DVB_RTL2830) += rtl2830.o obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o +obj-$(CONFIG_DVB_AF9033) += af9033.o diff --git a/drivers/media/dvb/frontends/af9033.c b/drivers/media/dvb/frontends/af9033.c new file mode 100644 index 000000000000..2cb1f8d6955e --- /dev/null +++ b/drivers/media/dvb/frontends/af9033.c @@ -0,0 +1,919 @@ +/* + * Afatech AF9033 demodulator driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "af9033_priv.h" + +struct af9033_state { + struct i2c_adapter *i2c; + struct dvb_frontend fe; + struct af9033_config cfg; + + u32 bandwidth_hz; + bool ts_mode_parallel; + bool ts_mode_serial; +}; + +/* write multiple registers */ +static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val, + int len) +{ + int ret; + u8 buf[3 + len]; + struct i2c_msg msg[1] = { + { + .addr = state->cfg.i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + buf[0] = (reg >> 16) & 0xff; + buf[1] = (reg >> 8) & 0xff; + buf[2] = (reg >> 0) & 0xff; + memcpy(&buf[3], val, len); + + ret = i2c_transfer(state->i2c, msg, 1); + if (ret == 1) { + ret = 0; + } else { + printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n", + __func__, ret, reg, len); + ret = -EREMOTEIO; + } + + return ret; +} + +/* read multiple registers */ +static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len) +{ + int ret; + u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff, + (reg >> 0) & 0xff }; + struct i2c_msg msg[2] = { + { + .addr = state->cfg.i2c_addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf + }, { + .addr = state->cfg.i2c_addr, + .flags = I2C_M_RD, + .len = len, + .buf = val + } + }; + + ret = i2c_transfer(state->i2c, msg, 2); + if (ret == 2) { + ret = 0; + } else { + printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n", + __func__, ret, reg, len); + ret = -EREMOTEIO; + } + + return ret; +} + + +/* write single register */ +static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val) +{ + return af9033_wr_regs(state, reg, &val, 1); +} + +/* read single register */ +static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val) +{ + return af9033_rd_regs(state, reg, val, 1); +} + +/* write single register with mask */ +static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val, + u8 mask) +{ + int ret; + u8 tmp; + + /* no need for read if whole reg is written */ + if (mask != 0xff) { + ret = af9033_rd_regs(state, reg, &tmp, 1); + if (ret) + return ret; + + val &= mask; + tmp &= ~mask; + val |= tmp; + } + + return af9033_wr_regs(state, reg, &val, 1); +} + +/* read single register with mask */ +static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val, + u8 mask) +{ + int ret, i; + u8 tmp; + + ret = af9033_rd_regs(state, reg, &tmp, 1); + if (ret) + return ret; + + tmp &= mask; + + /* find position of the first bit */ + for (i = 0; i < 8; i++) { + if ((mask >> i) & 0x01) + break; + } + *val = tmp >> i; + + return 0; +} + +static u32 af9033_div(u32 a, u32 b, u32 x) +{ + u32 r = 0, c = 0, i; + + pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x); + + if (a > b) { + c = a / b; + a = a - c * b; + } + + for (i = 0; i < x; i++) { + if (a >= b) { + r += 1; + a -= b; + } + a <<= 1; + r <<= 1; + } + r = (c << (u32)x) + r; + + pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r); + + return r; +} + +static void af9033_release(struct dvb_frontend *fe) +{ + struct af9033_state *state = fe->demodulator_priv; + + kfree(state); +} + +static int af9033_init(struct dvb_frontend *fe) +{ + struct af9033_state *state = fe->demodulator_priv; + int ret, i, len; + const struct reg_val *init; + u8 buf[4]; + u32 adc_cw, clock_cw; + struct reg_val_mask tab[] = { + { 0x80fb24, 0x00, 0x08 }, + { 0x80004c, 0x00, 0xff }, + { 0x00f641, state->cfg.tuner, 0xff }, + { 0x80f5ca, 0x01, 0x01 }, + { 0x80f715, 0x01, 0x01 }, + { 0x00f41f, 0x04, 0x04 }, + { 0x00f41a, 0x01, 0x01 }, + { 0x80f731, 0x00, 0x01 }, + { 0x00d91e, 0x00, 0x01 }, + { 0x00d919, 0x00, 0x01 }, + { 0x80f732, 0x00, 0x01 }, + { 0x00d91f, 0x00, 0x01 }, + { 0x00d91a, 0x00, 0x01 }, + { 0x80f730, 0x00, 0x01 }, + { 0x80f778, 0x00, 0xff }, + { 0x80f73c, 0x01, 0x01 }, + { 0x80f776, 0x00, 0x01 }, + { 0x00d8fd, 0x01, 0xff }, + { 0x00d830, 0x01, 0xff }, + { 0x00d831, 0x00, 0xff }, + { 0x00d832, 0x00, 0xff }, + { 0x80f985, state->ts_mode_serial, 0x01 }, + { 0x80f986, state->ts_mode_parallel, 0x01 }, + { 0x00d827, 0x00, 0xff }, + { 0x00d829, 0x00, 0xff }, + }; + + /* program clock control */ + clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul); + buf[0] = (clock_cw >> 0) & 0xff; + buf[1] = (clock_cw >> 8) & 0xff; + buf[2] = (clock_cw >> 16) & 0xff; + buf[3] = (clock_cw >> 24) & 0xff; + + pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock, + clock_cw); + + ret = af9033_wr_regs(state, 0x800025, buf, 4); + if (ret < 0) + goto err; + + /* program ADC control */ + for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { + if (clock_adc_lut[i].clock == state->cfg.clock) + break; + } + + adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul); + buf[0] = (adc_cw >> 0) & 0xff; + buf[1] = (adc_cw >> 8) & 0xff; + buf[2] = (adc_cw >> 16) & 0xff; + + pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc, + adc_cw); + + ret = af9033_wr_regs(state, 0x80f1cd, buf, 3); + if (ret < 0) + goto err; + + /* program register table */ + for (i = 0; i < ARRAY_SIZE(tab); i++) { + ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val, + tab[i].mask); + if (ret < 0) + goto err; + } + + /* settings for TS interface */ + if (state->cfg.ts_mode == AF9033_TS_MODE_USB) { + ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01); + if (ret < 0) + goto err; + + ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01); + if (ret < 0) + goto err; + } else { + ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01); + if (ret < 0) + goto err; + + ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01); + if (ret < 0) + goto err; + } + + /* load OFSM settings */ + pr_debug("%s: load ofsm settings\n", __func__); + len = ARRAY_SIZE(ofsm_init); + init = ofsm_init; + for (i = 0; i < len; i++) { + ret = af9033_wr_reg(state, init[i].reg, init[i].val); + if (ret < 0) + goto err; + } + + /* load tuner specific settings */ + pr_debug("%s: load tuner specific settings\n", + __func__); + switch (state->cfg.tuner) { + case AF9033_TUNER_TUA9001: + len = ARRAY_SIZE(tuner_init_tua9001); + init = tuner_init_tua9001; + break; + case AF9033_TUNER_FC0011: + len = ARRAY_SIZE(tuner_init_fc0011); + init = tuner_init_fc0011; + break; + case AF9033_TUNER_MXL5007T: + len = ARRAY_SIZE(tuner_init_mxl5007t); + init = tuner_init_mxl5007t; + break; + case AF9033_TUNER_TDA18218: + len = ARRAY_SIZE(tuner_init_tda18218); + init = tuner_init_tda18218; + break; + default: + pr_debug("%s: unsupported tuner ID=%d\n", __func__, + state->cfg.tuner); + ret = -ENODEV; + goto err; + } + + for (i = 0; i < len; i++) { + ret = af9033_wr_reg(state, init[i].reg, init[i].val); + if (ret < 0) + goto err; + } + + state->bandwidth_hz = 0; /* force to program all parameters */ + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_sleep(struct dvb_frontend *fe) +{ + struct af9033_state *state = fe->demodulator_priv; + int ret, i; + u8 tmp; + + ret = af9033_wr_reg(state, 0x80004c, 1); + if (ret < 0) + goto err; + + ret = af9033_wr_reg(state, 0x800000, 0); + if (ret < 0) + goto err; + + for (i = 100, tmp = 1; i && tmp; i--) { + ret = af9033_rd_reg(state, 0x80004c, &tmp); + if (ret < 0) + goto err; + + usleep_range(200, 10000); + } + + pr_debug("%s: loop=%d\n", __func__, i); + + if (i == 0) { + ret = -ETIMEDOUT; + goto err; + } + + ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08); + if (ret < 0) + goto err; + + /* prevent current leak (?) */ + if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) { + /* enable parallel TS */ + ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01); + if (ret < 0) + goto err; + + ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01); + if (ret < 0) + goto err; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_get_tune_settings(struct dvb_frontend *fe, + struct dvb_frontend_tune_settings *fesettings) +{ + fesettings->min_delay_ms = 800; + fesettings->step_size = 0; + fesettings->max_drift = 0; + + return 0; +} + +static int af9033_set_frontend(struct dvb_frontend *fe) +{ + struct af9033_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret, i, spec_inv; + u8 tmp, buf[3], bandwidth_reg_val; + u32 if_frequency, freq_cw, adc_freq; + + pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency, + c->bandwidth_hz); + + /* check bandwidth */ + switch (c->bandwidth_hz) { + case 6000000: + bandwidth_reg_val = 0x00; + break; + case 7000000: + bandwidth_reg_val = 0x01; + break; + case 8000000: + bandwidth_reg_val = 0x02; + break; + default: + pr_debug("%s: invalid bandwidth_hz\n", __func__); + ret = -EINVAL; + goto err; + } + + /* program tuner */ + if (fe->ops.tuner_ops.set_params) + fe->ops.tuner_ops.set_params(fe); + + /* program CFOE coefficients */ + if (c->bandwidth_hz != state->bandwidth_hz) { + for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) { + if (coeff_lut[i].clock == state->cfg.clock && + coeff_lut[i].bandwidth_hz == c->bandwidth_hz) { + break; + } + } + ret = af9033_wr_regs(state, 0x800001, + coeff_lut[i].val, sizeof(coeff_lut[i].val)); + } + + /* program frequency control */ + if (c->bandwidth_hz != state->bandwidth_hz) { + spec_inv = state->cfg.spec_inv ? -1 : 1; + + for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) { + if (clock_adc_lut[i].clock == state->cfg.clock) + break; + } + adc_freq = clock_adc_lut[i].adc; + + /* get used IF frequency */ + if (fe->ops.tuner_ops.get_if_frequency) + fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency); + else + if_frequency = 0; + + while (if_frequency > (adc_freq / 2)) + if_frequency -= adc_freq; + + if (if_frequency >= 0) + spec_inv *= -1; + else + if_frequency *= -1; + + freq_cw = af9033_div(if_frequency, adc_freq, 23ul); + + if (spec_inv == -1) + freq_cw *= -1; + + /* get adc multiplies */ + ret = af9033_rd_reg(state, 0x800045, &tmp); + if (ret < 0) + goto err; + + if (tmp == 1) + freq_cw /= 2; + + buf[0] = (freq_cw >> 0) & 0xff; + buf[1] = (freq_cw >> 8) & 0xff; + buf[2] = (freq_cw >> 16) & 0x7f; + ret = af9033_wr_regs(state, 0x800029, buf, 3); + if (ret < 0) + goto err; + + state->bandwidth_hz = c->bandwidth_hz; + } + + ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03); + if (ret < 0) + goto err; + + ret = af9033_wr_reg(state, 0x800040, 0x00); + if (ret < 0) + goto err; + + ret = af9033_wr_reg(state, 0x800047, 0x00); + if (ret < 0) + goto err; + + ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01); + if (ret < 0) + goto err; + + if (c->frequency <= 230000000) + tmp = 0x00; /* VHF */ + else + tmp = 0x01; /* UHF */ + + ret = af9033_wr_reg(state, 0x80004b, tmp); + if (ret < 0) + goto err; + + ret = af9033_wr_reg(state, 0x800000, 0x00); + if (ret < 0) + goto err; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_get_frontend(struct dvb_frontend *fe) +{ + struct af9033_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + int ret; + u8 buf[8]; + + pr_debug("%s\n", __func__); + + /* read all needed registers */ + ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf)); + if (ret < 0) + goto err; + + switch ((buf[0] >> 0) & 3) { + case 0: + c->transmission_mode = TRANSMISSION_MODE_2K; + break; + case 1: + c->transmission_mode = TRANSMISSION_MODE_8K; + break; + } + + switch ((buf[1] >> 0) & 3) { + case 0: + c->guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + c->guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + c->guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + c->guard_interval = GUARD_INTERVAL_1_4; + break; + } + + switch ((buf[2] >> 0) & 7) { + case 0: + c->hierarchy = HIERARCHY_NONE; + break; + case 1: + c->hierarchy = HIERARCHY_1; + break; + case 2: + c->hierarchy = HIERARCHY_2; + break; + case 3: + c->hierarchy = HIERARCHY_4; + break; + } + + switch ((buf[3] >> 0) & 3) { + case 0: + c->modulation = QPSK; + break; + case 1: + c->modulation = QAM_16; + break; + case 2: + c->modulation = QAM_64; + break; + } + + switch ((buf[4] >> 0) & 3) { + case 0: + c->bandwidth_hz = 6000000; + break; + case 1: + c->bandwidth_hz = 7000000; + break; + case 2: + c->bandwidth_hz = 8000000; + break; + } + + switch ((buf[6] >> 0) & 7) { + case 0: + c->code_rate_HP = FEC_1_2; + break; + case 1: + c->code_rate_HP = FEC_2_3; + break; + case 2: + c->code_rate_HP = FEC_3_4; + break; + case 3: + c->code_rate_HP = FEC_5_6; + break; + case 4: + c->code_rate_HP = FEC_7_8; + break; + case 5: + c->code_rate_HP = FEC_NONE; + break; + } + + switch ((buf[7] >> 0) & 7) { + case 0: + c->code_rate_LP = FEC_1_2; + break; + case 1: + c->code_rate_LP = FEC_2_3; + break; + case 2: + c->code_rate_LP = FEC_3_4; + break; + case 3: + c->code_rate_LP = FEC_5_6; + break; + case 4: + c->code_rate_LP = FEC_7_8; + break; + case 5: + c->code_rate_LP = FEC_NONE; + break; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct af9033_state *state = fe->demodulator_priv; + int ret; + u8 tmp; + + *status = 0; + + /* radio channel status, 0=no result, 1=has signal, 2=no signal */ + ret = af9033_rd_reg(state, 0x800047, &tmp); + if (ret < 0) + goto err; + + /* has signal */ + if (tmp == 0x01) + *status |= FE_HAS_SIGNAL; + + if (tmp != 0x02) { + /* TPS lock */ + ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01); + if (ret < 0) + goto err; + + if (tmp) + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI; + + /* full lock */ + ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01); + if (ret < 0) + goto err; + + if (tmp) + *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | + FE_HAS_VITERBI | FE_HAS_SYNC | + FE_HAS_LOCK; + } + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct af9033_state *state = fe->demodulator_priv; + int ret, i, len; + u8 buf[3], tmp; + u32 snr_val; + const struct val_snr *uninitialized_var(snr_lut); + + /* read value */ + ret = af9033_rd_regs(state, 0x80002c, buf, 3); + if (ret < 0) + goto err; + + snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0]; + + /* read current modulation */ + ret = af9033_rd_reg(state, 0x80f903, &tmp); + if (ret < 0) + goto err; + + switch ((tmp >> 0) & 3) { + case 0: + len = ARRAY_SIZE(qpsk_snr_lut); + snr_lut = qpsk_snr_lut; + break; + case 1: + len = ARRAY_SIZE(qam16_snr_lut); + snr_lut = qam16_snr_lut; + break; + case 2: + len = ARRAY_SIZE(qam64_snr_lut); + snr_lut = qam64_snr_lut; + break; + default: + goto err; + } + + for (i = 0; i < len; i++) { + tmp = snr_lut[i].snr; + + if (snr_val < snr_lut[i].val) + break; + } + + *snr = tmp * 10; /* dB/10 */ + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct af9033_state *state = fe->demodulator_priv; + int ret; + u8 strength2; + + /* read signal strength of 0-100 scale */ + ret = af9033_rd_reg(state, 0x800048, &strength2); + if (ret < 0) + goto err; + + /* scale value to 0x0000-0xffff */ + *strength = strength2 * 0xffff / 100; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + *ber = 0; + + return 0; +} + +static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + *ucblocks = 0; + + return 0; +} + +static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) +{ + struct af9033_state *state = fe->demodulator_priv; + int ret; + + pr_debug("%s: enable=%d\n", __func__, enable); + + ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01); + if (ret < 0) + goto err; + + return 0; + +err: + pr_debug("%s: failed=%d\n", __func__, ret); + + return ret; +} + +static struct dvb_frontend_ops af9033_ops; + +struct dvb_frontend *af9033_attach(const struct af9033_config *config, + struct i2c_adapter *i2c) +{ + int ret; + struct af9033_state *state; + u8 buf[8]; + + pr_debug("%s:\n", __func__); + + /* allocate memory for the internal state */ + state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL); + if (state == NULL) + goto err; + + /* setup the state */ + state->i2c = i2c; + memcpy(&state->cfg, config, sizeof(struct af9033_config)); + + if (state->cfg.clock != 12000000) { + printk(KERN_INFO "af9033: unsupported clock=%d, only " \ + "12000000 Hz is supported currently\n", + state->cfg.clock); + goto err; + } + + /* firmware version */ + ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4); + if (ret < 0) + goto err; + + ret = af9033_rd_regs(state, 0x804191, &buf[4], 4); + if (ret < 0) + goto err; + + printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \ + "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + + /* configure internal TS mode */ + switch (state->cfg.ts_mode) { + case AF9033_TS_MODE_PARALLEL: + state->ts_mode_parallel = true; + break; + case AF9033_TS_MODE_SERIAL: + state->ts_mode_serial = true; + break; + case AF9033_TS_MODE_USB: + /* usb mode for AF9035 */ + default: + break; + } + + /* create dvb_frontend */ + memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops)); + state->fe.demodulator_priv = state; + + return &state->fe; + +err: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(af9033_attach); + +static struct dvb_frontend_ops af9033_ops = { + .delsys = { SYS_DVBT }, + .info = { + .name = "Afatech AF9033 (DVB-T)", + .frequency_min = 174000000, + .frequency_max = 862000000, + .frequency_stepsize = 250000, + .frequency_tolerance = 0, + .caps = FE_CAN_FEC_1_2 | + FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_QAM_16 | + FE_CAN_QAM_64 | + FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO | + FE_CAN_RECOVER | + FE_CAN_MUTE_TS + }, + + .release = af9033_release, + + .init = af9033_init, + .sleep = af9033_sleep, + + .get_tune_settings = af9033_get_tune_settings, + .set_frontend = af9033_set_frontend, + .get_frontend = af9033_get_frontend, + + .read_status = af9033_read_status, + .read_snr = af9033_read_snr, + .read_signal_strength = af9033_read_signal_strength, + .read_ber = af9033_read_ber, + .read_ucblocks = af9033_read_ucblocks, + + .i2c_gate_ctrl = af9033_i2c_gate_ctrl, +}; + +MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); +MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/af9033.h b/drivers/media/dvb/frontends/af9033.h new file mode 100644 index 000000000000..9e302c3f0f7d --- /dev/null +++ b/drivers/media/dvb/frontends/af9033.h @@ -0,0 +1,75 @@ +/* + * Afatech AF9033 demodulator driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef AF9033_H +#define AF9033_H + +struct af9033_config { + /* + * I2C address + */ + u8 i2c_addr; + + /* + * clock Hz + * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000, + * 30000000, 36000000, 20480000, 16384000 + */ + u32 clock; + + /* + * tuner + */ +#define AF9033_TUNER_TUA9001 0x27 /* Infineon TUA 9001 */ +#define AF9033_TUNER_FC0011 0x28 /* Fitipower FC0011 */ +#define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */ +#define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */ + u8 tuner; + + /* + * TS settings + */ +#define AF9033_TS_MODE_USB 0 +#define AF9033_TS_MODE_PARALLEL 1 +#define AF9033_TS_MODE_SERIAL 2 + u8 ts_mode:2; + + /* + * input spectrum inversion + */ + bool spec_inv; +}; + + +#if defined(CONFIG_DVB_AF9033) || \ + (defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE)) +extern struct dvb_frontend *af9033_attach(const struct af9033_config *config, + struct i2c_adapter *i2c); +#else +static inline struct dvb_frontend *af9033_attach( + const struct af9033_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* AF9033_H */ diff --git a/drivers/media/dvb/frontends/af9033_priv.h b/drivers/media/dvb/frontends/af9033_priv.h new file mode 100644 index 000000000000..0b783b9ed75e --- /dev/null +++ b/drivers/media/dvb/frontends/af9033_priv.h @@ -0,0 +1,470 @@ +/* + * Afatech AF9033 demodulator driver + * + * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> + * Copyright (C) 2012 Antti Palosaari <crope@iki.fi> + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef AF9033_PRIV_H +#define AF9033_PRIV_H + +#include "dvb_frontend.h" +#include "af9033.h" + +struct reg_val { + u32 reg; + u8 val; +}; + +struct reg_val_mask { + u32 reg; + u8 val; + u8 mask; +}; + +struct coeff { + u32 clock; + u32 bandwidth_hz; + u8 val[36]; +}; + +struct clock_adc { + u32 clock; + u32 adc; +}; + +struct val_snr { + u32 val; + u8 snr; +}; + +/* Xtal clock vs. ADC clock lookup table */ +static const struct clock_adc clock_adc_lut[] = { + { 16384000, 20480000 }, + { 20480000, 20480000 }, + { 36000000, 20250000 }, + { 30000000, 20156250 }, + { 26000000, 20583333 }, + { 28000000, 20416667 }, + { 32000000, 20500000 }, + { 34000000, 20187500 }, + { 24000000, 20500000 }, + { 22000000, 20625000 }, + { 12000000, 20250000 }, +}; + +/* pre-calculated coeff lookup table */ +static const struct coeff coeff_lut[] = { + /* 12.000 MHz */ + { 12000000, 8000000, { + 0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, + 0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5, + 0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73, + 0x95, 0x72, 0x37, 0x02, 0xce, 0x01 } + }, + { 12000000, 7000000, { + 0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, + 0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b, + 0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65, + 0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 } + }, + { 12000000, 6000000, { + 0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, + 0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60, + 0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56, + 0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 } + }, +}; + +/* QPSK SNR lookup table */ +static const struct val_snr qpsk_snr_lut[] = { + { 0x0b4771, 0 }, + { 0x0c1aed, 1 }, + { 0x0d0d27, 2 }, + { 0x0e4d19, 3 }, + { 0x0e5da8, 4 }, + { 0x107097, 5 }, + { 0x116975, 6 }, + { 0x1252d9, 7 }, + { 0x131fa4, 8 }, + { 0x13d5e1, 9 }, + { 0x148e53, 10 }, + { 0x15358b, 11 }, + { 0x15dd29, 12 }, + { 0x168112, 13 }, + { 0x170b61, 14 }, + { 0x17a532, 15 }, + { 0x180f94, 16 }, + { 0x186ed2, 17 }, + { 0x18b271, 18 }, + { 0x18e118, 19 }, + { 0x18ff4b, 20 }, + { 0x190af1, 21 }, + { 0x191451, 22 }, + { 0xffffff, 23 }, +}; + +/* QAM16 SNR lookup table */ +static const struct val_snr qam16_snr_lut[] = { + { 0x04f0d5, 0 }, + { 0x05387a, 1 }, + { 0x0573a4, 2 }, + { 0x05a99e, 3 }, + { 0x05cc80, 4 }, + { 0x05eb62, 5 }, + { 0x05fecf, 6 }, + { 0x060b80, 7 }, + { 0x062501, 8 }, + { 0x064865, 9 }, + { 0x069604, 10 }, + { 0x06f356, 11 }, + { 0x07706a, 12 }, + { 0x0804d3, 13 }, + { 0x089d1a, 14 }, + { 0x093e3d, 15 }, + { 0x09e35d, 16 }, + { 0x0a7c3c, 17 }, + { 0x0afaf8, 18 }, + { 0x0b719d, 19 }, + { 0x0bda6a, 20 }, + { 0x0c0c75, 21 }, + { 0x0c3f7d, 22 }, + { 0x0c5e62, 23 }, + { 0x0c6c31, 24 }, + { 0x0c7925, 25 }, + { 0xffffff, 26 }, +}; + +/* QAM64 SNR lookup table */ +static const struct val_snr qam64_snr_lut[] = { + { 0x0256d0, 0 }, + { 0x027a65, 1 }, + { 0x029873, 2 }, + { 0x02b7fe, 3 }, + { 0x02cf1e, 4 }, + { 0x02e234, 5 }, + { 0x02f409, 6 }, + { 0x030046, 7 }, + { 0x030844, 8 }, + { 0x030a02, 9 }, + { 0x030cde, 10 }, + { 0x031031, 11 }, + { 0x03144c, 12 }, + { 0x0315dd, 13 }, + { 0x031920, 14 }, + { 0x0322d0, 15 }, + { 0x0339fc, 16 }, + { 0x0364a1, 17 }, + { 0x038bcc, 18 }, + { 0x03c7d3, 19 }, + { 0x0408cc, 20 }, + { 0x043bed, 21 }, + { 0x048061, 22 }, + { 0x04be95, 23 }, + { 0x04fa7d, 24 }, + { 0x052405, 25 }, + { 0x05570d, 26 }, + { 0x059feb, 27 }, + { 0x05bf38, 28 }, + { 0xffffff, 29 }, +}; + +static const struct reg_val ofsm_init[] = { + { 0x800051, 0x01 }, + { 0x800070, 0x0a }, + { 0x80007e, 0x04 }, + { 0x800081, 0x0a }, + { 0x80008a, 0x01 }, + { 0x80008e, 0x01 }, + { 0x800092, 0x06 }, + { 0x800099, 0x01 }, + { 0x80009f, 0xe1 }, + { 0x8000a0, 0xcf }, + { 0x8000a3, 0x01 }, + { 0x8000a5, 0x01 }, + { 0x8000a6, 0x01 }, + { 0x8000a9, 0x00 }, + { 0x8000aa, 0x01 }, + { 0x8000ab, 0x01 }, + { 0x8000b0, 0x01 }, + { 0x8000c0, 0x05 }, + { 0x8000c4, 0x19 }, + { 0x80f000, 0x0f }, + { 0x80f016, 0x10 }, + { 0x80f017, 0x04 }, + { 0x80f018, 0x05 }, + { 0x80f019, 0x04 }, + { 0x80f01a, 0x05 }, + { 0x80f021, 0x03 }, + { 0x80f022, 0x0a }, + { 0x80f023, 0x0a }, + { 0x80f02b, 0x00 }, + { 0x80f02c, 0x01 }, + { 0x80f064, 0x03 }, + { 0x80f065, 0xf9 }, + { 0x80f066, 0x03 }, + { 0x80f067, 0x01 }, + { 0x80f06f, 0xe0 }, + { 0x80f070, 0x03 }, + { 0x80f072, 0x0f }, + { 0x80f073, 0x03 }, + { 0x80f078, 0x00 }, + { 0x80f087, 0x00 }, + { 0x80f09b, 0x3f }, + { 0x80f09c, 0x00 }, + { 0x80f09d, 0x20 }, + { 0x80f09e, 0x00 }, + { 0x80f09f, 0x0c }, + { 0x80f0a0, 0x00 }, + { 0x80f130, 0x04 }, + { 0x80f132, 0x04 }, + { 0x80f144, 0x1a }, + { 0x80f146, 0x00 }, + { 0x80f14a, 0x01 }, + { 0x80f14c, 0x00 }, + { 0x80f14d, 0x00 }, + { 0x80f14f, 0x04 }, + { 0x80f158, 0x7f }, + { 0x80f15a, 0x00 }, + { 0x80f15b, 0x08 }, + { 0x80f15d, 0x03 }, + { 0x80f15e, 0x05 }, + { 0x80f163, 0x05 }, + { 0x80f166, 0x01 }, + { 0x80f167, 0x40 }, + { 0x80f168, 0x0f }, + { 0x80f17a, 0x00 }, + { 0x80f17b, 0x00 }, + { 0x80f183, 0x01 }, + { 0x80f19d, 0x40 }, + { 0x80f1bc, 0x36 }, + { 0x80f1bd, 0x00 }, + { 0x80f1cb, 0xa0 }, + { 0x80f1cc, 0x01 }, + { 0x80f204, 0x10 }, + { 0x80f214, 0x00 }, + { 0x80f40e, 0x0a }, + { 0x80f40f, 0x40 }, + { 0x80f410, 0x08 }, + { 0x80f55f, 0x0a }, + { 0x80f561, 0x15 }, + { 0x80f562, 0x20 }, + { 0x80f5df, 0xfb }, + { 0x80f5e0, 0x00 }, + { 0x80f5e3, 0x09 }, + { 0x80f5e4, 0x01 }, + { 0x80f5e5, 0x01 }, + { 0x80f5f8, 0x01 }, + { 0x80f5fd, 0x01 }, + { 0x80f600, 0x05 }, + { 0x80f601, 0x08 }, + { 0x80f602, 0x0b }, + { 0x80f603, 0x0e }, + { 0x80f604, 0x11 }, + { 0x80f605, 0x14 }, + { 0x80f606, 0x17 }, + { 0x80f607, 0x1f }, + { 0x80f60e, 0x00 }, + { 0x80f60f, 0x04 }, + { 0x80f610, 0x32 }, + { 0x80f611, 0x10 }, + { 0x80f707, 0xfc }, + { 0x80f708, 0x00 }, + { 0x80f709, 0x37 }, + { 0x80f70a, 0x00 }, + { 0x80f78b, 0x01 }, + { 0x80f80f, 0x40 }, + { 0x80f810, 0x54 }, + { 0x80f811, 0x5a }, + { 0x80f905, 0x01 }, + { 0x80fb06, 0x03 }, + { 0x80fd8b, 0x00 }, +}; + +/* Infineon TUA 9001 tuner init + AF9033_TUNER_TUA9001 = 0x27 */ +static const struct reg_val tuner_init_tua9001[] = { + { 0x800046, 0x27 }, + { 0x800057, 0x00 }, + { 0x800058, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x80006d, 0x00 }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800074, 0x01 }, + { 0x800075, 0x03 }, + { 0x800076, 0x02 }, + { 0x800077, 0x00 }, + { 0x800078, 0x01 }, + { 0x800079, 0x00 }, + { 0x80007a, 0x7e }, + { 0x80007b, 0x3e }, + { 0x800093, 0x00 }, + { 0x800094, 0x01 }, + { 0x800095, 0x02 }, + { 0x800096, 0x01 }, + { 0x800098, 0x0a }, + { 0x80009b, 0x05 }, + { 0x80009c, 0x80 }, + { 0x8000b3, 0x00 }, + { 0x8000c1, 0x01 }, + { 0x8000c2, 0x00 }, + { 0x80f007, 0x00 }, + { 0x80f01f, 0x82 }, + { 0x80f020, 0x00 }, + { 0x80f029, 0x82 }, + { 0x80f02a, 0x00 }, + { 0x80f047, 0x00 }, + { 0x80f054, 0x00 }, + { 0x80f055, 0x00 }, + { 0x80f077, 0x01 }, + { 0x80f1e6, 0x00 }, +}; + +/* Fitipower fc0011 tuner init + AF9033_TUNER_FC0011 = 0x28 */ +static const struct reg_val tuner_init_fc0011[] = { + { 0x800046, AF9033_TUNER_FC0011 }, + { 0x800057, 0x00 }, + { 0x800058, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0xa5 }, + { 0x80006e, 0x01 }, + { 0x800071, 0x0A }, + { 0x800072, 0x02 }, + { 0x800074, 0x01 }, + { 0x800079, 0x01 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x80009b, 0x2D }, + { 0x80009c, 0x60 }, + { 0x80009d, 0x23 }, + { 0x8000a4, 0x50 }, + { 0x8000ad, 0x50 }, + { 0x8000b3, 0x01 }, + { 0x8000b7, 0x88 }, + { 0x8000b8, 0xa6 }, + { 0x8000c3, 0x01 }, + { 0x8000c4, 0x01 }, + { 0x8000c7, 0x69 }, + { 0x80F007, 0x00 }, + { 0x80F00A, 0x1B }, + { 0x80F00B, 0x1B }, + { 0x80F00C, 0x1B }, + { 0x80F00D, 0x1B }, + { 0x80F00E, 0xFF }, + { 0x80F00F, 0x01 }, + { 0x80F010, 0x00 }, + { 0x80F011, 0x02 }, + { 0x80F012, 0xFF }, + { 0x80F013, 0x01 }, + { 0x80F014, 0x00 }, + { 0x80F015, 0x02 }, + { 0x80F01B, 0xEF }, + { 0x80F01C, 0x01 }, + { 0x80F01D, 0x0f }, + { 0x80F01E, 0x02 }, + { 0x80F01F, 0x6E }, + { 0x80F020, 0x00 }, + { 0x80F025, 0xDE }, + { 0x80F026, 0x00 }, + { 0x80F027, 0x0A }, + { 0x80F028, 0x03 }, + { 0x80F029, 0x6E }, + { 0x80F02A, 0x00 }, + { 0x80F047, 0x00 }, + { 0x80F054, 0x00 }, + { 0x80F055, 0x00 }, + { 0x80F077, 0x01 }, + { 0x80F1E6, 0x00 }, +}; + +/* MaxLinear MxL5007T tuner init + AF9033_TUNER_MXL5007T = 0xa0 */ +static const struct reg_val tuner_init_mxl5007t[] = { + { 0x800046, 0x1b }, + { 0x800057, 0x01 }, + { 0x800058, 0x01 }, + { 0x80005f, 0x00 }, + { 0x800060, 0x00 }, + { 0x800068, 0x96 }, + { 0x800071, 0x05 }, + { 0x800072, 0x02 }, + { 0x800074, 0x01 }, + { 0x800079, 0x01 }, + { 0x800093, 0x00 }, + { 0x800094, 0x00 }, + { 0x800095, 0x00 }, + { 0x800096, 0x00 }, + { 0x8000b3, 0x01 }, + { 0x8000c1, 0x01 }, + { 0x8000c2, 0x00 }, + { 0x80f007, 0x00 }, + { 0x80f00c, 0x19 }, + { 0x80f00d, 0x1a }, + { 0x80f012, 0xda }, + { 0x80f013, 0x00 }, + { 0x80f014, 0x00 }, + { 0x80f015, 0x02 }, + { 0x80f01f, 0x82 }, + { 0x80f020, 0x00 }, + { 0x80f029, 0x82 }, + { 0x80f02a, 0x00 }, + { 0x80f077, 0x02 }, + { 0x80f1e6, 0x00 }, +}; + +/* NXP TDA 18218HN tuner init + AF9033_TUNER_TDA18218 = 0xa1 */ +static const struct reg_val tuner_init_tda18218[] = { + {0x800046, 0xa1}, + {0x800057, 0x01}, + {0x800058, 0x01}, + {0x80005f, 0x00}, + {0x800060, 0x00}, + {0x800071, 0x05}, + {0x800072, 0x02}, + {0x800074, 0x01}, + {0x800079, 0x01}, + {0x800093, 0x00}, + {0x800094, 0x00}, + {0x800095, 0x00}, + {0x800096, 0x00}, + {0x8000b3, 0x01}, + {0x8000c3, 0x01}, + {0x8000c4, 0x00}, + {0x80f007, 0x00}, + {0x80f00c, 0x19}, + {0x80f00d, 0x1a}, + {0x80f012, 0xda}, + {0x80f013, 0x00}, + {0x80f014, 0x00}, + {0x80f015, 0x02}, + {0x80f01f, 0x82}, + {0x80f020, 0x00}, + {0x80f029, 0x82}, + {0x80f02a, 0x00}, + {0x80f077, 0x02}, + {0x80f1e6, 0x00}, +}; + +#endif /* AF9033_PRIV_H */ + diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 2e639ce6f256..235c0e349820 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c @@ -29,6 +29,7 @@ #include <linux/videodev2.h> /* kernel radio structs */ #include <linux/mutex.h> #include <linux/io.h> /* outb, outb_p */ +#include <linux/pnp.h> #include <linux/slab.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-device.h> @@ -283,6 +284,16 @@ static const struct radio_isa_ops gemtek_ops = { static const int gemtek_ioports[] = { 0x20c, 0x30c, 0x24c, 0x34c, 0x248, 0x28c }; +#ifdef CONFIG_PNP +static struct pnp_device_id gemtek_pnp_devices[] = { + /* AOpen FX-3D/Pro Radio */ + {.id = "ADS7183", .driver_data = 0}, + {.id = ""} +}; + +MODULE_DEVICE_TABLE(pnp, gemtek_pnp_devices); +#endif + static struct radio_isa_driver gemtek_driver = { .driver = { .match = radio_isa_match, @@ -292,6 +303,14 @@ static struct radio_isa_driver gemtek_driver = { .name = "radio-gemtek", }, }, +#ifdef CONFIG_PNP + .pnp_driver = { + .name = "radio-gemtek", + .id_table = gemtek_pnp_devices, + .probe = radio_isa_pnp_probe, + .remove = radio_isa_pnp_remove, + }, +#endif .io_params = io, .radio_nr_params = radio_nr, .io_ports = gemtek_ioports, @@ -305,12 +324,18 @@ static struct radio_isa_driver gemtek_driver = { static int __init gemtek_init(void) { gemtek_driver.probe = probe; +#ifdef CONFIG_PNP + pnp_register_driver(&gemtek_driver.pnp_driver); +#endif return isa_register_driver(&gemtek_driver.driver, GEMTEK_MAX); } static void __exit gemtek_exit(void) { hardmute = 1; /* Turn off PLL */ +#ifdef CONFIG_PNP + pnp_unregister_driver(&gemtek_driver.pnp_driver); +#endif isa_unregister_driver(&gemtek_driver.driver); } diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c index 06f906351fad..ed9039f8571c 100644 --- a/drivers/media/radio/radio-isa.c +++ b/drivers/media/radio/radio-isa.c @@ -199,56 +199,31 @@ static bool radio_isa_valid_io(const struct radio_isa_driver *drv, int io) return false; } -int radio_isa_probe(struct device *pdev, unsigned int dev) +struct radio_isa_card *radio_isa_alloc(struct radio_isa_driver *drv, + struct device *pdev) { - struct radio_isa_driver *drv = pdev->platform_data; - const struct radio_isa_ops *ops = drv->ops; struct v4l2_device *v4l2_dev; - struct radio_isa_card *isa; - int res; + struct radio_isa_card *isa = drv->ops->alloc(); + if (!isa) + return NULL; - isa = drv->ops->alloc(); - if (isa == NULL) - return -ENOMEM; dev_set_drvdata(pdev, isa); isa->drv = drv; - isa->io = drv->io_params[dev]; v4l2_dev = &isa->v4l2_dev; strlcpy(v4l2_dev->name, dev_name(pdev), sizeof(v4l2_dev->name)); - if (drv->probe && ops->probe) { - int i; - - for (i = 0; i < drv->num_of_io_ports; ++i) { - int io = drv->io_ports[i]; - - if (request_region(io, drv->region_size, v4l2_dev->name)) { - bool found = ops->probe(isa, io); - - release_region(io, drv->region_size); - if (found) { - isa->io = io; - break; - } - } - } - } - - if (!radio_isa_valid_io(drv, isa->io)) { - int i; + return isa; +} - if (isa->io < 0) - return -ENODEV; - v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", - drv->io_ports[0]); - for (i = 1; i < drv->num_of_io_ports; i++) - printk(KERN_CONT "/0x%03x", drv->io_ports[i]); - printk(KERN_CONT ".\n"); - kfree(isa); - return -EINVAL; - } +int radio_isa_common_probe(struct radio_isa_card *isa, struct device *pdev, + int radio_nr, unsigned region_size) +{ + const struct radio_isa_driver *drv = isa->drv; + const struct radio_isa_ops *ops = drv->ops; + struct v4l2_device *v4l2_dev = &isa->v4l2_dev; + int res; - if (!request_region(isa->io, drv->region_size, v4l2_dev->name)) { + if (!request_region(isa->io, region_size, v4l2_dev->name)) { v4l2_err(v4l2_dev, "port 0x%x already in use\n", isa->io); kfree(isa); return -EBUSY; @@ -301,8 +276,8 @@ int radio_isa_probe(struct device *pdev, unsigned int dev) v4l2_err(v4l2_dev, "Could not setup card\n"); goto err_node_reg; } - res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, - drv->radio_nr_params[dev]); + res = video_register_device(&isa->vdev, VFL_TYPE_RADIO, radio_nr); + if (res < 0) { v4l2_err(v4l2_dev, "Could not register device node\n"); goto err_node_reg; @@ -317,24 +292,110 @@ err_node_reg: err_hdl: v4l2_device_unregister(&isa->v4l2_dev); err_dev_reg: - release_region(isa->io, drv->region_size); + release_region(isa->io, region_size); kfree(isa); return res; } -EXPORT_SYMBOL_GPL(radio_isa_probe); -int radio_isa_remove(struct device *pdev, unsigned int dev) +int radio_isa_common_remove(struct radio_isa_card *isa, unsigned region_size) { - struct radio_isa_card *isa = dev_get_drvdata(pdev); const struct radio_isa_ops *ops = isa->drv->ops; ops->s_mute_volume(isa, true, isa->volume ? isa->volume->cur.val : 0); video_unregister_device(&isa->vdev); v4l2_ctrl_handler_free(&isa->hdl); v4l2_device_unregister(&isa->v4l2_dev); - release_region(isa->io, isa->drv->region_size); + release_region(isa->io, region_size); v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card); kfree(isa); return 0; } + +int radio_isa_probe(struct device *pdev, unsigned int dev) +{ + struct radio_isa_driver *drv = pdev->platform_data; + const struct radio_isa_ops *ops = drv->ops; + struct v4l2_device *v4l2_dev; + struct radio_isa_card *isa; + + isa = radio_isa_alloc(drv, pdev); + if (!isa) + return -ENOMEM; + isa->io = drv->io_params[dev]; + v4l2_dev = &isa->v4l2_dev; + + if (drv->probe && ops->probe) { + int i; + + for (i = 0; i < drv->num_of_io_ports; ++i) { + int io = drv->io_ports[i]; + + if (request_region(io, drv->region_size, v4l2_dev->name)) { + bool found = ops->probe(isa, io); + + release_region(io, drv->region_size); + if (found) { + isa->io = io; + break; + } + } + } + } + + if (!radio_isa_valid_io(drv, isa->io)) { + int i; + + if (isa->io < 0) + return -ENODEV; + v4l2_err(v4l2_dev, "you must set an I/O address with io=0x%03x", + drv->io_ports[0]); + for (i = 1; i < drv->num_of_io_ports; i++) + printk(KERN_CONT "/0x%03x", drv->io_ports[i]); + printk(KERN_CONT ".\n"); + kfree(isa); + return -EINVAL; + } + + return radio_isa_common_probe(isa, pdev, drv->radio_nr_params[dev], + drv->region_size); +} +EXPORT_SYMBOL_GPL(radio_isa_probe); + +int radio_isa_remove(struct device *pdev, unsigned int dev) +{ + struct radio_isa_card *isa = dev_get_drvdata(pdev); + + return radio_isa_common_remove(isa, isa->drv->region_size); +} EXPORT_SYMBOL_GPL(radio_isa_remove); + +#ifdef CONFIG_PNP +int radio_isa_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) +{ + struct pnp_driver *pnp_drv = to_pnp_driver(dev->dev.driver); + struct radio_isa_driver *drv = container_of(pnp_drv, + struct radio_isa_driver, pnp_driver); + struct radio_isa_card *isa; + + if (!pnp_port_valid(dev, 0)) + return -ENODEV; + + isa = radio_isa_alloc(drv, &dev->dev); + if (!isa) + return -ENOMEM; + + isa->io = pnp_port_start(dev, 0); + + return radio_isa_common_probe(isa, &dev->dev, drv->radio_nr_params[0], + pnp_port_len(dev, 0)); +} +EXPORT_SYMBOL_GPL(radio_isa_pnp_probe); + +void radio_isa_pnp_remove(struct pnp_dev *dev) +{ + struct radio_isa_card *isa = dev_get_drvdata(&dev->dev); + + radio_isa_common_remove(isa, pnp_port_len(dev, 0)); +} +EXPORT_SYMBOL_GPL(radio_isa_pnp_remove); +#endif diff --git a/drivers/media/radio/radio-isa.h b/drivers/media/radio/radio-isa.h index 8a0ea84d86de..ba4c01f1bd0c 100644 --- a/drivers/media/radio/radio-isa.h +++ b/drivers/media/radio/radio-isa.h @@ -24,6 +24,7 @@ #define _RADIO_ISA_H_ #include <linux/isa.h> +#include <linux/pnp.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-ctrls.h> @@ -76,6 +77,9 @@ struct radio_isa_ops { /* Top level structure needed to instantiate the cards */ struct radio_isa_driver { struct isa_driver driver; +#ifdef CONFIG_PNP + struct pnp_driver pnp_driver; +#endif const struct radio_isa_ops *ops; /* The module_param_array with the specified I/O ports */ int *io_params; @@ -101,5 +105,10 @@ struct radio_isa_driver { int radio_isa_match(struct device *pdev, unsigned int dev); int radio_isa_probe(struct device *pdev, unsigned int dev); int radio_isa_remove(struct device *pdev, unsigned int dev); +#ifdef CONFIG_PNP +int radio_isa_pnp_probe(struct pnp_dev *dev, + const struct pnp_device_id *dev_id); +void radio_isa_pnp_remove(struct pnp_dev *dev); +#endif #endif diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index b275c5d0fe9a..b1f844c64fde 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c @@ -17,6 +17,7 @@ #include <linux/videodev2.h> /* kernel radio structs */ #include <linux/mutex.h> #include <linux/io.h> /* outb, outb_p */ +#include <linux/slab.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include "radio-isa.h" diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c index baf907b3ce76..26fa043d3de7 100644 --- a/drivers/media/rc/ati_remote.c +++ b/drivers/media/rc/ati_remote.c @@ -1,7 +1,7 @@ /* * USB ATI Remote support * - * Copyright (c) 2011 Anssi Hannula <anssi.hannula@iki.fi> + * Copyright (c) 2011, 2012 Anssi Hannula <anssi.hannula@iki.fi> * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev * @@ -151,13 +151,35 @@ MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes"); #undef err #define err(format, arg...) printk(KERN_ERR format , ## arg) +struct ati_receiver_type { + /* either default_keymap or get_default_keymap should be set */ + const char *default_keymap; + const char *(*get_default_keymap)(struct usb_interface *interface); +}; + +static const char *get_medion_keymap(struct usb_interface *interface) +{ + struct usb_device *udev = interface_to_usbdev(interface); + + /* The receiver shipped with the "Digitainer" variant helpfully has + * a single additional bit set in its descriptor. */ + if (udev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_WAKEUP) + return RC_MAP_MEDION_X10_DIGITAINER; + + return RC_MAP_MEDION_X10; +} + +static const struct ati_receiver_type type_ati = { .default_keymap = RC_MAP_ATI_X10 }; +static const struct ati_receiver_type type_medion = { .get_default_keymap = get_medion_keymap }; +static const struct ati_receiver_type type_firefly = { .default_keymap = RC_MAP_SNAPSTREAM_FIREFLY }; + static struct usb_device_id ati_remote_table[] = { - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_ATI_X10 }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_MEDION_X10 }, - { USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)RC_MAP_SNAPSTREAM_FIREFLY }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_ati }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_medion }, + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID), .driver_info = (unsigned long)&type_firefly }, {} /* Terminating entry */ }; @@ -445,6 +467,7 @@ static void ati_remote_input_report(struct urb *urb) int acc; int remote_num; unsigned char scancode; + u32 wheel_keycode = KEY_RESERVED; int i; /* @@ -484,26 +507,33 @@ static void ati_remote_input_report(struct urb *urb) */ scancode = data[2] & 0x7f; - /* Look up event code index in the mouse translation table. */ - for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { - if (scancode == ati_remote_tbl[i].data) { - index = i; - break; + dbginfo(&ati_remote->interface->dev, + "channel 0x%02x; key data %02x, scancode %02x\n", + remote_num, data[2], scancode); + + if (scancode >= 0x70) { + /* + * This is either a mouse or scrollwheel event, depending on + * the remote/keymap. + * Get the keycode assigned to scancode 0x78/0x70. If it is + * set, assume this is a scrollwheel up/down event. + */ + wheel_keycode = rc_g_keycode_from_table(ati_remote->rdev, + scancode & 0x78); + + if (wheel_keycode == KEY_RESERVED) { + /* scrollwheel was not mapped, assume mouse */ + + /* Look up event code index in the mouse translation table. */ + for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { + if (scancode == ati_remote_tbl[i].data) { + index = i; + break; + } + } } } - if (index >= 0) { - dbginfo(&ati_remote->interface->dev, - "channel 0x%02x; mouse data %02x; index %d; keycode %d\n", - remote_num, data[2], index, ati_remote_tbl[index].code); - if (!dev) - return; /* no mouse device */ - } else - dbginfo(&ati_remote->interface->dev, - "channel 0x%02x; key data %02x, scancode %02x\n", - remote_num, data[2], scancode); - - if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) { input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, @@ -542,15 +572,29 @@ static void ati_remote_input_report(struct urb *urb) if (index < 0) { /* Not a mouse event, hand it to rc-core. */ - - /* - * We don't use the rc-core repeat handling yet as - * it would cause ghost repeats which would be a - * regression for this driver. - */ - rc_keydown_notimeout(ati_remote->rdev, scancode, - data[2]); - rc_keyup(ati_remote->rdev); + int count = 1; + + if (wheel_keycode != KEY_RESERVED) { + /* + * This is a scrollwheel event, send the + * scroll up (0x78) / down (0x70) scancode + * repeatedly as many times as indicated by + * rest of the scancode. + */ + count = (scancode & 0x07) + 1; + scancode &= 0x78; + } + + while (count--) { + /* + * We don't use the rc-core repeat handling yet as + * it would cause ghost repeats which would be a + * regression for this driver. + */ + rc_keydown_notimeout(ati_remote->rdev, scancode, + data[2]); + rc_keyup(ati_remote->rdev); + } return; } @@ -766,6 +810,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de struct usb_device *udev = interface_to_usbdev(interface); struct usb_host_interface *iface_host = interface->cur_altsetting; struct usb_endpoint_descriptor *endpoint_in, *endpoint_out; + struct ati_receiver_type *type = (struct ati_receiver_type *)id->driver_info; struct ati_remote *ati_remote; struct input_dev *input_dev; struct rc_dev *rc_dev; @@ -827,10 +872,15 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de snprintf(ati_remote->mouse_name, sizeof(ati_remote->mouse_name), "%s mouse", ati_remote->rc_name); - if (id->driver_info) - rc_dev->map_name = (const char *)id->driver_info; - else - rc_dev->map_name = RC_MAP_ATI_X10; + rc_dev->map_name = RC_MAP_ATI_X10; /* default map */ + + /* set default keymap according to receiver model */ + if (type) { + if (type->default_keymap) + rc_dev->map_name = type->default_keymap; + else if (type->get_default_keymap) + rc_dev->map_name = type->get_default_keymap(interface); + } ati_remote_rc_init(ati_remote); mutex_init(&ati_remote->open_mutex); diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 95e630998aaf..a82025121345 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -46,9 +46,9 @@ static int ir_raw_event_thread(void *data) while (!kthread_should_stop()) { spin_lock_irq(&raw->lock); - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + retval = kfifo_len(&raw->kfifo); - if (!retval) { + if (retval < sizeof(ev)) { set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) @@ -59,11 +59,9 @@ static int ir_raw_event_thread(void *data) continue; } + retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); spin_unlock_irq(&raw->lock); - - BUG_ON(retval != sizeof(ev)); - mutex_lock(&ir_raw_handler_lock); list_for_each_entry(handler, &ir_raw_handler_list, list) handler->decode(raw->dev, ev); diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile index 49ce2662f56b..38ff6e0e099a 100644 --- a/drivers/media/rc/keymaps/Makefile +++ b/drivers/media/rc/keymaps/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ rc-lme2510.o \ rc-manli.o \ rc-medion-x10.o \ + rc-medion-x10-digitainer.o \ rc-msi-digivox-ii.o \ rc-msi-digivox-iii.o \ rc-msi-tvanywhere.o \ diff --git a/drivers/media/rc/keymaps/rc-medion-x10-digitainer.c b/drivers/media/rc/keymaps/rc-medion-x10-digitainer.c new file mode 100644 index 000000000000..0a5ce84d9fd8 --- /dev/null +++ b/drivers/media/rc/keymaps/rc-medion-x10-digitainer.c @@ -0,0 +1,115 @@ +/* + * Medion X10 RF remote keytable (Digitainer variant) + * + * Copyright (C) 2012 Anssi Hannula <anssi.hannula@iki.fi> + * + * This keymap is for a variant that has a distinctive scrollwheel instead of + * up/down buttons (tested with P/N 40009936 / 20018268), reportedly + * originally shipped with Medion Digitainer but now sold separately simply as + * an "X10" remote. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/module.h> +#include <media/rc-map.h> + +static struct rc_map_table medion_x10_digitainer[] = { + { 0x02, KEY_POWER }, + + { 0x2c, KEY_TV }, + { 0x2d, KEY_VIDEO }, + { 0x04, KEY_DVD }, /* CD/DVD */ + { 0x16, KEY_TEXT }, /* "teletext" icon, i.e. a screen with lines */ + { 0x06, KEY_AUDIO }, + { 0x2e, KEY_RADIO }, + { 0x31, KEY_EPG }, /* a screen with an open book */ + { 0x05, KEY_IMAGES }, /* Photo */ + { 0x2f, KEY_INFO }, + + { 0x78, KEY_UP }, /* scrollwheel up 1 notch */ + /* 0x79..0x7f: 2-8 notches, driver repeats 0x78 entry */ + + { 0x70, KEY_DOWN }, /* scrollwheel down 1 notch */ + /* 0x71..0x77: 2-8 notches, driver repeats 0x70 entry */ + + { 0x19, KEY_MENU }, + { 0x1d, KEY_LEFT }, + { 0x1e, KEY_OK }, /* scrollwheel press */ + { 0x1f, KEY_RIGHT }, + { 0x20, KEY_BACK }, + + { 0x09, KEY_VOLUMEUP }, + { 0x08, KEY_VOLUMEDOWN }, + { 0x00, KEY_MUTE }, + + { 0x1b, KEY_SELECT }, /* also has "U" rotated 90 degrees CCW */ + + { 0x0b, KEY_CHANNELUP }, + { 0x0c, KEY_CHANNELDOWN }, + { 0x1c, KEY_LAST }, + + { 0x32, KEY_RED }, /* also Audio */ + { 0x33, KEY_GREEN }, /* also Subtitle */ + { 0x34, KEY_YELLOW }, /* also Angle */ + { 0x35, KEY_BLUE }, /* also Title */ + + { 0x28, KEY_STOP }, + { 0x29, KEY_PAUSE }, + { 0x25, KEY_PLAY }, + { 0x21, KEY_PREVIOUS }, + { 0x18, KEY_CAMERA }, + { 0x23, KEY_NEXT }, + { 0x24, KEY_REWIND }, + { 0x27, KEY_RECORD }, + { 0x26, KEY_FORWARD }, + + { 0x0d, KEY_1 }, + { 0x0e, KEY_2 }, + { 0x0f, KEY_3 }, + { 0x10, KEY_4 }, + { 0x11, KEY_5 }, + { 0x12, KEY_6 }, + { 0x13, KEY_7 }, + { 0x14, KEY_8 }, + { 0x15, KEY_9 }, + { 0x17, KEY_0 }, +}; + +static struct rc_map_list medion_x10_digitainer_map = { + .map = { + .scan = medion_x10_digitainer, + .size = ARRAY_SIZE(medion_x10_digitainer), + .rc_type = RC_TYPE_OTHER, + .name = RC_MAP_MEDION_X10_DIGITAINER, + } +}; + +static int __init init_rc_map_medion_x10_digitainer(void) +{ + return rc_map_register(&medion_x10_digitainer_map); +} + +static void __exit exit_rc_map_medion_x10_digitainer(void) +{ + rc_map_unregister(&medion_x10_digitainer_map); +} + +module_init(init_rc_map_medion_x10_digitainer) +module_exit(exit_rc_map_medion_x10_digitainer) + +MODULE_DESCRIPTION("Medion X10 RF remote keytable (Digitainer variant)"); +MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index e581b37be789..a9cfb0f4be48 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -663,7 +663,7 @@ static const struct v4l2_queryctrl bttv_ctls[] = { .minimum = 0, .maximum = 65535, .step = 128, - .default_value = 32768, + .default_value = 27648, .type = V4L2_CTRL_TYPE_INTEGER, },{ .id = V4L2_CID_SATURATION, @@ -4394,7 +4394,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, if (!bttv_tvcards[btv->c.type].no_video) { bttv_register_video(btv); bt848_bright(btv,32768); - bt848_contrast(btv,32768); + bt848_contrast(btv, 27648); bt848_hue(btv,32768); bt848_sat(btv,32768); audio_mute(btv, 1); diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index f6f622e123bd..928ef0d0429f 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -49,10 +49,10 @@ config VIDEO_EM28XX_DVB Empiatech em28xx chips. config VIDEO_EM28XX_RC - bool "EM28XX Remote Controller support" + tristate "EM28XX Remote Controller support" depends on RC_CORE depends on VIDEO_EM28XX depends on !(RC_CORE=m && VIDEO_EM28XX=y) - default y + default VIDEO_EM28XX ---help--- Enables Remote Controller support on em28xx driver. diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile index 2abdf76c5203..c8b338d4be05 100644 --- a/drivers/media/video/em28xx/Makefile +++ b/drivers/media/video/em28xx/Makefile @@ -1,16 +1,15 @@ em28xx-y := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-y += em28xx-core.o em28xx-vbi.o -em28xx-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-input.o - em28xx-alsa-objs := em28xx-audio.o +em28xx-rc-objs := em28xx-input.o obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o +obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o ccflags-y += -Idrivers/media/video ccflags-y += -Idrivers/media/common/tuners ccflags-y += -Idrivers/media/dvb/dvb-core ccflags-y += -Idrivers/media/dvb/frontends - diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 9fd8cc7dbb23..0ac117c23c47 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2661,54 +2661,6 @@ static int em28xx_hint_board(struct em28xx *dev) return -1; } -/* ----------------------------------------------------------------------- */ -void em28xx_register_i2c_ir(struct em28xx *dev) -{ - /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ - /* at address 0x18, so if that address is needed for another board in */ - /* the future, please put it after 0x1f. */ - struct i2c_board_info info; - const unsigned short addr_list[] = { - 0x1f, 0x30, 0x47, I2C_CLIENT_END - }; - - if (disable_ir) - return; - - memset(&info, 0, sizeof(struct i2c_board_info)); - memset(&dev->init_data, 0, sizeof(dev->init_data)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - - /* detect & configure */ - switch (dev->model) { - case EM2800_BOARD_TERRATEC_CINERGY_200: - case EM2820_BOARD_TERRATEC_CINERGY_250: - dev->init_data.ir_codes = RC_MAP_EM_TERRATEC; - dev->init_data.get_key = em28xx_get_key_terratec; - dev->init_data.name = "i2c IR (EM28XX Terratec)"; - break; - case EM2820_BOARD_PINNACLE_USB_2: - dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; - dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; - dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; - break; - case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: - dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; - dev->init_data.get_key = em28xx_get_key_em_haup; - dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; - break; - case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; - dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; - dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; - break; - } - - if (dev->init_data.name) - info.platform_data = &dev->init_data; - i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL); -} - void em28xx_card_setup(struct em28xx *dev) { /* @@ -2849,13 +2801,6 @@ void em28xx_card_setup(struct em28xx *dev) break; } -#if defined(CONFIG_MODULES) && defined(MODULE) - if (dev->board.has_ir_i2c && !disable_ir) - request_module("ir-kbd-i2c"); -#endif - if (dev->board.has_snapshot_button) - em28xx_register_snapshot_button(dev); - if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) { em28xx_errdev("\n\n"); em28xx_errdev("The support for this board weren't " @@ -2929,9 +2874,6 @@ void em28xx_card_setup(struct em28xx *dev) } em28xx_tuner_setup(dev); - - if(!disable_ir) - em28xx_ir_init(dev); } @@ -2948,6 +2890,8 @@ static void request_module_async(struct work_struct *work) if (dev->board.has_dvb) request_module("em28xx-dvb"); + if (dev->board.has_ir_i2c && !disable_ir) + request_module("em28xx-rc"); } static void request_modules(struct em28xx *dev) @@ -2972,12 +2916,6 @@ static void flush_request_modules(struct em28xx *dev) */ void em28xx_release_resources(struct em28xx *dev) { - if (dev->sbutton_input_dev) - em28xx_deregister_snapshot_button(dev); - - if (dev->ir) - em28xx_ir_fini(dev); - /*FIXME: I2C IR should be disconnected */ em28xx_release_analog_resources(dev); diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 53a9fb91e97e..5717bdee8f1b 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -139,6 +139,7 @@ int em28xx_read_reg(struct em28xx *dev, u16 reg) { return em28xx_read_reg_req(dev, USB_REQ_GET_STATUS, reg); } +EXPORT_SYMBOL_GPL(em28xx_read_reg); /* * em28xx_write_regs_req() @@ -205,6 +206,7 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) return rc; } +EXPORT_SYMBOL_GPL(em28xx_write_regs); /* Write a single register */ int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val) @@ -239,6 +241,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, return em28xx_write_regs(dev, reg, &newval, 1); } +EXPORT_SYMBOL_GPL(em28xx_write_reg_bits); /* * em28xx_is_ac97_ready() @@ -666,7 +669,6 @@ int em28xx_capture_start(struct em28xx *dev, int start) return rc; } -EXPORT_SYMBOL_GPL(em28xx_capture_start); int em28xx_vbi_supported(struct em28xx *dev) { @@ -975,7 +977,6 @@ void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) else isoc_bufs = &dev->isoc_ctl.analog_bufs; - dev->isoc_ctl.nfields = -1; for (i = 0; i < isoc_bufs->num_bufs; i++) { urb = isoc_bufs->urb[i]; if (urb) { @@ -1008,6 +1009,31 @@ void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode) EXPORT_SYMBOL_GPL(em28xx_uninit_isoc); /* + * Stop URBs + */ +void em28xx_stop_urbs(struct em28xx *dev) +{ + int i; + struct urb *urb; + struct em28xx_usb_isoc_bufs *isoc_bufs = &dev->isoc_ctl.digital_bufs; + + em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n"); + + for (i = 0; i < isoc_bufs->num_bufs; i++) { + urb = isoc_bufs->urb[i]; + if (urb) { + if (!irqs_disabled()) + usb_kill_urb(urb); + else + usb_unlink_urb(urb); + } + } + + em28xx_capture_start(dev, 0); +} +EXPORT_SYMBOL_GPL(em28xx_stop_urbs); + +/* * Allocate URBs */ int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode, diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 503a8d5b5382..2d73ee2abf7e 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -183,7 +183,7 @@ static int em28xx_stop_streaming(struct em28xx_dvb *dvb) { struct em28xx *dev = dvb->adapter.priv; - em28xx_capture_start(dev, 0); + em28xx_stop_urbs(dev); em28xx_set_mode(dev, EM28XX_SUSPEND); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index a88e169dba23..185db65b766e 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -553,9 +553,6 @@ int em28xx_i2c_register(struct em28xx *dev) if (i2c_scan) em28xx_do_i2c_scan(dev); - /* Instantiate the IR receiver device, if present */ - em28xx_register_i2c_ir(dev); - return 0; } diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 2630b265b0e8..fce5f7680c99 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -80,7 +80,7 @@ struct em28xx_IR { I2C IR based get keycodes - should be used with ir-kbd-i2c **********************************************************/ -int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char b; @@ -108,7 +108,7 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } -int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[2]; u16 code; @@ -157,7 +157,7 @@ int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) return 1; } -int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, +static int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { unsigned char buf[3]; @@ -179,7 +179,8 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, return 1; } -int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) +static int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, + u32 *ir_raw) { unsigned char subaddr, keydetect, key; @@ -387,7 +388,138 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) return rc; } -int em28xx_ir_init(struct em28xx *dev) +static void em28xx_register_i2c_ir(struct em28xx *dev) +{ + /* Leadtek winfast tv USBII deluxe can find a non working IR-device */ + /* at address 0x18, so if that address is needed for another board in */ + /* the future, please put it after 0x1f. */ + struct i2c_board_info info; + const unsigned short addr_list[] = { + 0x1f, 0x30, 0x47, I2C_CLIENT_END + }; + + memset(&info, 0, sizeof(struct i2c_board_info)); + memset(&dev->init_data, 0, sizeof(dev->init_data)); + strlcpy(info.type, "ir_video", I2C_NAME_SIZE); + + /* detect & configure */ + switch (dev->model) { + case EM2800_BOARD_TERRATEC_CINERGY_200: + case EM2820_BOARD_TERRATEC_CINERGY_250: + dev->init_data.ir_codes = RC_MAP_EM_TERRATEC; + dev->init_data.get_key = em28xx_get_key_terratec; + dev->init_data.name = "i2c IR (EM28XX Terratec)"; + break; + case EM2820_BOARD_PINNACLE_USB_2: + dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY; + dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey; + dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)"; + break; + case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: + dev->init_data.ir_codes = RC_MAP_HAUPPAUGE; + dev->init_data.get_key = em28xx_get_key_em_haup; + dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; + break; + case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: + dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; + dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; + dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; + break; + } + + if (dev->init_data.name) + info.platform_data = &dev->init_data; + i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL); +} + +/********************************************************** + Handle Webcam snapshot button + **********************************************************/ + +static void em28xx_query_sbutton(struct work_struct *work) +{ + /* Poll the register and see if the button is depressed */ + struct em28xx *dev = + container_of(work, struct em28xx, sbutton_query_work.work); + int ret; + + ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP); + + if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) { + u8 cleared; + /* Button is depressed, clear the register */ + cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT; + em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1); + + /* Not emulate the keypress */ + input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, + 1); + /* Now unpress the key */ + input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, + 0); + } + + /* Schedule next poll */ + schedule_delayed_work(&dev->sbutton_query_work, + msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); +} + +static void em28xx_register_snapshot_button(struct em28xx *dev) +{ + struct input_dev *input_dev; + int err; + + em28xx_info("Registering snapshot button...\n"); + input_dev = input_allocate_device(); + if (!input_dev) { + em28xx_errdev("input_allocate_device failed\n"); + return; + } + + usb_make_path(dev->udev, dev->snapshot_button_path, + sizeof(dev->snapshot_button_path)); + strlcat(dev->snapshot_button_path, "/sbutton", + sizeof(dev->snapshot_button_path)); + INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton); + + input_dev->name = "em28xx snapshot button"; + input_dev->phys = dev->snapshot_button_path; + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit); + input_dev->keycodesize = 0; + input_dev->keycodemax = 0; + input_dev->id.bustype = BUS_USB; + input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); + input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); + input_dev->id.version = 1; + input_dev->dev.parent = &dev->udev->dev; + + err = input_register_device(input_dev); + if (err) { + em28xx_errdev("input_register_device failed\n"); + input_free_device(input_dev); + return; + } + + dev->sbutton_input_dev = input_dev; + schedule_delayed_work(&dev->sbutton_query_work, + msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); + return; + +} + +static void em28xx_deregister_snapshot_button(struct em28xx *dev) +{ + if (dev->sbutton_input_dev != NULL) { + em28xx_info("Deregistering snapshot button\n"); + cancel_delayed_work_sync(&dev->sbutton_query_work); + input_unregister_device(dev->sbutton_input_dev); + dev->sbutton_input_dev = NULL; + } + return; +} + +static int em28xx_ir_init(struct em28xx *dev) { struct em28xx_IR *ir; struct rc_dev *rc; @@ -448,6 +580,15 @@ int em28xx_ir_init(struct em28xx *dev) if (err) goto err_out_stop; + em28xx_register_i2c_ir(dev); + +#if defined(CONFIG_MODULES) && defined(MODULE) + if (dev->board.has_ir_i2c) + request_module("ir-kbd-i2c"); +#endif + if (dev->board.has_snapshot_button) + em28xx_register_snapshot_button(dev); + return 0; err_out_stop: @@ -458,10 +599,12 @@ int em28xx_ir_init(struct em28xx *dev) return err; } -int em28xx_ir_fini(struct em28xx *dev) +static int em28xx_ir_fini(struct em28xx *dev) { struct em28xx_IR *ir = dev->ir; + em28xx_deregister_snapshot_button(dev); + /* skip detach on non attached boards */ if (!ir) return 0; @@ -475,89 +618,26 @@ int em28xx_ir_fini(struct em28xx *dev) return 0; } -/********************************************************** - Handle Webcam snapshot button - **********************************************************/ +static struct em28xx_ops rc_ops = { + .id = EM28XX_RC, + .name = "Em28xx Input Extension", + .init = em28xx_ir_init, + .fini = em28xx_ir_fini, +}; -static void em28xx_query_sbutton(struct work_struct *work) +static int __init em28xx_rc_register(void) { - /* Poll the register and see if the button is depressed */ - struct em28xx *dev = - container_of(work, struct em28xx, sbutton_query_work.work); - int ret; - - ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP); - - if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) { - u8 cleared; - /* Button is depressed, clear the register */ - cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT; - em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1); - - /* Not emulate the keypress */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 1); - /* Now unpress the key */ - input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY, - 0); - } - - /* Schedule next poll */ - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); + return em28xx_register_extension(&rc_ops); } -void em28xx_register_snapshot_button(struct em28xx *dev) +static void __exit em28xx_rc_unregister(void) { - struct input_dev *input_dev; - int err; - - em28xx_info("Registering snapshot button...\n"); - input_dev = input_allocate_device(); - if (!input_dev) { - em28xx_errdev("input_allocate_device failed\n"); - return; - } - - usb_make_path(dev->udev, dev->snapshot_button_path, - sizeof(dev->snapshot_button_path)); - strlcat(dev->snapshot_button_path, "/sbutton", - sizeof(dev->snapshot_button_path)); - INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton); - - input_dev->name = "em28xx snapshot button"; - input_dev->phys = dev->snapshot_button_path; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); - set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit); - input_dev->keycodesize = 0; - input_dev->keycodemax = 0; - input_dev->id.bustype = BUS_USB; - input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); - input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct); - input_dev->id.version = 1; - input_dev->dev.parent = &dev->udev->dev; - - err = input_register_device(input_dev); - if (err) { - em28xx_errdev("input_register_device failed\n"); - input_free_device(input_dev); - return; - } - - dev->sbutton_input_dev = input_dev; - schedule_delayed_work(&dev->sbutton_query_work, - msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL)); - return; - + em28xx_unregister_extension(&rc_ops); } -void em28xx_deregister_snapshot_button(struct em28xx *dev) -{ - if (dev->sbutton_input_dev != NULL) { - em28xx_info("Deregistering snapshot button\n"); - cancel_delayed_work_sync(&dev->sbutton_query_work); - input_unregister_device(dev->sbutton_input_dev); - dev->sbutton_input_dev = NULL; - } - return; -} +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_DESCRIPTION("Em28xx Input driver"); + +module_init(em28xx_rc_register); +module_exit(em28xx_rc_unregister); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 324b695c0724..bcc41603c193 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1305,9 +1305,7 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) if (0 == INPUT(i)->type) return -EINVAL; - dev->ctl_input = i; - - video_mux(dev, dev->ctl_input); + video_mux(dev, i); return 0; } @@ -2518,7 +2516,6 @@ int em28xx_register_analog_devices(struct em28xx *dev) dev->norm = em28xx_video_template.current_norm; v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm); dev->interlaced = EM28XX_INTERLACED_DEFAULT; - dev->ctl_input = 0; /* Analog specific initialization */ dev->format = &format[0]; @@ -2532,7 +2529,7 @@ int em28xx_register_analog_devices(struct em28xx *dev) em28xx_set_video_format(dev, format[0].fourcc, maxw, norm_maxh(dev)); - video_mux(dev, dev->ctl_input); + video_mux(dev, 0); /* Audio defaults */ dev->mute = 1; diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 2868b19f8b54..9a2bd5c40163 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -226,24 +226,10 @@ struct em28xx_usb_isoc_ctl { /* isoc transfer buffers for digital mode */ struct em28xx_usb_isoc_bufs digital_bufs; - /* Last buffer command and region */ - u8 cmd; - int pos, size, pktsize; - - /* Last field: ODD or EVEN? */ - int field; - - /* Stores incomplete commands */ - u32 tmp_buf; - int tmp_buf_len; - /* Stores already requested buffers */ struct em28xx_buffer *vid_buf; struct em28xx_buffer *vbi_buf; - /* Stores the number of received fields */ - int nfields; - /* isoc urb callback */ int (*isoc_copy) (struct em28xx *dev, struct urb *urb); @@ -467,6 +453,7 @@ enum em28xx_dev_state { /* em28xx extensions */ #define EM28XX_AUDIO 0x10 #define EM28XX_DVB 0x20 +#define EM28XX_RC 0x30 /* em28xx resource types (used for res_get/res_lock etc */ #define EM28XX_RESOURCE_VIDEO 0x01 @@ -695,6 +682,7 @@ int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode, int max_packets, int num_bufs, int max_pkt_size, int (*isoc_copy) (struct em28xx *dev, struct urb *urb)); void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode); +void em28xx_stop_urbs(struct em28xx *dev); int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev); int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode); int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio); @@ -715,40 +703,9 @@ extern void em28xx_card_setup(struct em28xx *dev); extern struct em28xx_board em28xx_boards[]; extern struct usb_device_id em28xx_id_table[]; extern const unsigned int em28xx_bcount; -void em28xx_register_i2c_ir(struct em28xx *dev); int em28xx_tuner_callback(void *ptr, int component, int command, int arg); void em28xx_release_resources(struct em28xx *dev); -/* Provided by em28xx-input.c */ - -#ifdef CONFIG_VIDEO_EM28XX_RC - -int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); -int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); -int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw); -int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key, - u32 *ir_raw); -void em28xx_register_snapshot_button(struct em28xx *dev); -void em28xx_deregister_snapshot_button(struct em28xx *dev); - -int em28xx_ir_init(struct em28xx *dev); -int em28xx_ir_fini(struct em28xx *dev); - -#else - -#define em28xx_get_key_terratec NULL -#define em28xx_get_key_em_haup NULL -#define em28xx_get_key_pinnacle_usb_grey NULL -#define em28xx_get_key_winfast_usbii_deluxe NULL - -static inline void em28xx_register_snapshot_button(struct em28xx *dev) {} -static inline void em28xx_deregister_snapshot_button(struct em28xx *dev) {} -static inline int em28xx_ir_init(struct em28xx *dev) { return 0; } -static inline int em28xx_ir_fini(struct em28xx *dev) { return 0; } - -#endif - /* Provided by em28xx-vbi.c */ extern struct videobuf_queue_ops em28xx_vbi_qops; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index c9663e885b9f..9ff69b5a87e2 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -746,8 +746,9 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) return res; } -unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) +unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) { + unsigned long req_events = poll_requested_events(wait); struct ivtv_open_id *id = fh2id(filp->private_data); struct ivtv *itv = id->itv; struct ivtv_stream *s = &itv->streams[id->type]; @@ -755,7 +756,8 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait) unsigned res = 0; /* Start a capture if there is none */ - if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { + if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && + (req_events & (POLLIN | POLLRDNORM))) { int rc; rc = ivtv_start_capture(id); diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c index ba89a7401c8c..55ac1735e85b 100644 --- a/drivers/media/video/mx2_emmaprp.c +++ b/drivers/media/video/mx2_emmaprp.c @@ -755,7 +755,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, memset(src_vq, 0, sizeof(*src_vq)); src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - src_vq->io_modes = VB2_MMAP; + src_vq->io_modes = VB2_MMAP | VB2_USERPTR; src_vq->drv_priv = ctx; src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); src_vq->ops = &emmaprp_qops; @@ -767,7 +767,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, memset(dst_vq, 0, sizeof(*dst_vq)); dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_vq->io_modes = VB2_MMAP; + dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); dst_vq->ops = &emmaprp_qops; diff --git a/drivers/media/video/omap3isp/ispqueue.h b/drivers/media/video/omap3isp/ispqueue.h index 92c5a12157d5..908dfd712e8e 100644 --- a/drivers/media/video/omap3isp/ispqueue.h +++ b/drivers/media/video/omap3isp/ispqueue.h @@ -90,7 +90,7 @@ struct isp_video_buffer { void *vaddr; /* For userspace buffers. */ - unsigned long vm_flags; + vm_flags_t vm_flags; unsigned long offset; unsigned int npages; struct page **pages; diff --git a/drivers/media/video/ov5642.c b/drivers/media/video/ov5642.c index 80e07794ac8e..0bc93313d37a 100644 --- a/drivers/media/video/ov5642.c +++ b/drivers/media/video/ov5642.c @@ -1025,8 +1025,6 @@ static int ov5642_probe(struct i2c_client *client, priv->crop_rect.height = OV5642_DEFAULT_HEIGHT; priv->crop_rect.left = (OV5642_MAX_WIDTH - OV5642_DEFAULT_WIDTH) / 2; priv->crop_rect.top = (OV5642_MAX_HEIGHT - OV5642_DEFAULT_HEIGHT) / 2; - priv->crop_rect.width = OV5642_DEFAULT_WIDTH; - priv->crop_rect.height = OV5642_DEFAULT_HEIGHT; priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH; priv->total_height = BLANKING_MIN_HEIGHT; diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 122fbd0081eb..f3370a87cbc0 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -625,10 +625,19 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf, static unsigned int pwc_video_poll(struct file *file, poll_table *wait) { struct pwc_device *pdev = video_drvdata(file); + unsigned long req_events = poll_requested_events(wait); if (!pdev->udev) return POLL_ERR; + if ((req_events & (POLLIN | POLLRDNORM)) && + pdev->vb_queue.num_buffers == 0 && + !pdev->iso_init) { + /* This poll will start a read stream, check capt_file */ + if (pwc_test_n_set_capt_file(pdev, file)) + return POLL_ERR; + } + return vb2_poll(&pdev->vb_queue, file, wait); } diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 2834e3e65b39..c1ba1a060c93 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -1166,4 +1166,6 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = { .vidioc_enum_frameintervals = pwc_enum_frameintervals, .vidioc_g_parm = pwc_g_parm, .vidioc_s_parm = pwc_s_parm, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, }; diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 4894cbb1c547..37845def41c5 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1826,8 +1826,7 @@ static void s2255_destroy(struct s2255_dev *dev) usb_free_urb(dev->fw_data->fw_urb); dev->fw_data->fw_urb = NULL; } - if (dev->fw_data->fw) - release_firmware(dev->fw_data->fw); + release_firmware(dev->fw_data->fw); kfree(dev->fw_data->pfw_data); kfree(dev->fw_data); /* reset the DSP so firmware can be reloaded next time */ diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index b06efd208328..dc18ba510986 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c @@ -83,7 +83,9 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM | 1 << ST_CAPT_ISP_STREAM); - if (!suspend) + if (suspend) + fimc->state |= (1 << ST_CAPT_SUSPENDED); + else fimc->state &= ~(1 << ST_CAPT_PEND | 1 << ST_CAPT_SUSPENDED); /* Release unused buffers */ @@ -99,7 +101,6 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend) else vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); } - set_bit(ST_CAPT_SUSPENDED, &fimc->state); fimc_hw_reset(fimc); cap->buf_index = 0; @@ -146,21 +147,22 @@ int fimc_capture_config_update(struct fimc_ctx *ctx) if (!test_bit(ST_CAPT_APPLY_CFG, &fimc->state)) return 0; - spin_lock(&ctx->slock); fimc_hw_set_camera_offset(fimc, &ctx->s_frame); + ret = fimc_set_scaler_info(ctx); - if (ret == 0) { - fimc_hw_set_prescaler(ctx); - fimc_hw_set_mainscaler(ctx); - fimc_hw_set_target_format(ctx); - fimc_hw_set_rotation(ctx); - fimc_prepare_dma_offset(ctx, &ctx->d_frame); - fimc_hw_set_out_dma(ctx); - if (fimc->variant->has_alpha) - fimc_hw_set_rgb_alpha(ctx); - clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); - } - spin_unlock(&ctx->slock); + if (ret) + return ret; + + fimc_hw_set_prescaler(ctx); + fimc_hw_set_mainscaler(ctx); + fimc_hw_set_target_format(ctx); + fimc_hw_set_rotation(ctx); + fimc_prepare_dma_offset(ctx, &ctx->d_frame); + fimc_hw_set_out_dma(ctx); + if (fimc->variant->has_alpha) + fimc_hw_set_rgb_alpha(ctx); + + clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); return ret; } @@ -1524,7 +1526,6 @@ int fimc_register_capture_device(struct fimc_dev *fimc, INIT_LIST_HEAD(&vid_cap->pending_buf_q); INIT_LIST_HEAD(&vid_cap->active_buf_q); - spin_lock_init(&ctx->slock); vid_cap->ctx = ctx; q = &fimc->vid_cap.vbq; diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index e184e650022a..7b90a897beeb 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -320,7 +320,7 @@ static int fimc_m2m_shutdown(struct fimc_ctx *ctx) if (!fimc_m2m_pending(fimc)) return 0; - fimc_ctx_state_lock_set(FIMC_CTX_SHUT, ctx); + fimc_ctx_state_set(FIMC_CTX_SHUT, ctx); ret = wait_event_timeout(fimc->irq_queue, !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx), @@ -430,14 +430,12 @@ static irqreturn_t fimc_irq_handler(int irq, void *priv) spin_unlock(&fimc->slock); fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE); - spin_lock(&ctx->slock); if (ctx->state & FIMC_CTX_SHUT) { ctx->state &= ~FIMC_CTX_SHUT; wake_up(&fimc->irq_queue); } - spin_unlock(&ctx->slock); + return IRQ_HANDLED; } - return IRQ_HANDLED; } else if (test_bit(ST_CAPT_PEND, &fimc->state)) { fimc_capture_irq_handler(fimc, !test_bit(ST_CAPT_JPEG, &fimc->state)); @@ -584,55 +582,11 @@ void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v); } -/** - * fimc_prepare_config - check dimensions, operation and color mode - * and pre-calculate offset and the scaling coefficients. - * - * @ctx: hardware context information - * @flags: flags indicating which parameters to check/update - * - * Return: 0 if dimensions are valid or non zero otherwise. - */ -int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) -{ - struct fimc_frame *s_frame, *d_frame; - struct vb2_buffer *vb = NULL; - int ret = 0; - - s_frame = &ctx->s_frame; - d_frame = &ctx->d_frame; - - if (flags & FIMC_PARAMS) { - /* Prepare the DMA offset ratios for scaler. */ - fimc_prepare_dma_offset(ctx, &ctx->s_frame); - fimc_prepare_dma_offset(ctx, &ctx->d_frame); - - if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) || - s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) { - err("out of scaler range"); - return -EINVAL; - } - fimc_set_yuv_order(ctx); - } - - if (flags & FIMC_SRC_ADDR) { - vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); - ret = fimc_prepare_addr(ctx, vb, s_frame, &s_frame->paddr); - if (ret) - return ret; - } - - if (flags & FIMC_DST_ADDR) { - vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); - ret = fimc_prepare_addr(ctx, vb, d_frame, &d_frame->paddr); - } - - return ret; -} - static void fimc_dma_run(void *priv) { + struct vb2_buffer *vb = NULL; struct fimc_ctx *ctx = priv; + struct fimc_frame *sf, *df; struct fimc_dev *fimc; unsigned long flags; u32 ret; @@ -643,10 +597,22 @@ static void fimc_dma_run(void *priv) fimc = ctx->fimc_dev; spin_lock_irqsave(&fimc->slock, flags); set_bit(ST_M2M_PEND, &fimc->state); + sf = &ctx->s_frame; + df = &ctx->d_frame; + + if (ctx->state & FIMC_PARAMS) { + /* Prepare the DMA offsets for scaler */ + fimc_prepare_dma_offset(ctx, sf); + fimc_prepare_dma_offset(ctx, df); + } + + vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); + ret = fimc_prepare_addr(ctx, vb, sf, &sf->paddr); + if (ret) + goto dma_unlock; - spin_lock(&ctx->slock); - ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR); - ret = fimc_prepare_config(ctx, ctx->state); + vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); + ret = fimc_prepare_addr(ctx, vb, df, &df->paddr); if (ret) goto dma_unlock; @@ -655,32 +621,26 @@ static void fimc_dma_run(void *priv) ctx->state |= FIMC_PARAMS; fimc->m2m.ctx = ctx; } - fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr); if (ctx->state & FIMC_PARAMS) { + fimc_set_yuv_order(ctx); fimc_hw_set_input_path(ctx); fimc_hw_set_in_dma(ctx); ret = fimc_set_scaler_info(ctx); - if (ret) { - spin_unlock(&fimc->slock); + if (ret) goto dma_unlock; - } fimc_hw_set_prescaler(ctx); fimc_hw_set_mainscaler(ctx); fimc_hw_set_target_format(ctx); fimc_hw_set_rotation(ctx); fimc_hw_set_effect(ctx, false); - } - - fimc_hw_set_output_path(ctx); - if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS)) - fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1); - - if (ctx->state & FIMC_PARAMS) { fimc_hw_set_out_dma(ctx); if (fimc->variant->has_alpha) fimc_hw_set_rgb_alpha(ctx); + fimc_hw_set_output_path(ctx); } + fimc_hw_set_input_addr(fimc, &sf->paddr); + fimc_hw_set_output_addr(fimc, &df->paddr, -1); fimc_activate_capture(ctx); @@ -688,7 +648,6 @@ static void fimc_dma_run(void *priv) FIMC_SRC_FMT | FIMC_DST_FMT); fimc_hw_activate_input_dma(fimc, true); dma_unlock: - spin_unlock(&ctx->slock); spin_unlock_irqrestore(&fimc->slock, flags); } @@ -827,9 +786,9 @@ static int fimc_s_ctrl(struct v4l2_ctrl *ctrl) unsigned long flags; int ret; - spin_lock_irqsave(&ctx->slock, flags); + spin_lock_irqsave(&ctx->fimc_dev->slock, flags); ret = __fimc_s_ctrl(ctx, ctrl); - spin_unlock_irqrestore(&ctx->slock, flags); + spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags); return ret; } @@ -1174,9 +1133,9 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, ctx->scaler.enabled = 1; if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) - fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); + fimc_ctx_state_set(FIMC_PARAMS | FIMC_DST_FMT, ctx); else - fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx); + fimc_ctx_state_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx); dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height); @@ -1363,7 +1322,7 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) f->width = cr->c.width; f->height = cr->c.height; - fimc_ctx_state_lock_set(FIMC_PARAMS, ctx); + fimc_ctx_state_set(FIMC_PARAMS, ctx); return 0; } @@ -1467,7 +1426,6 @@ static int fimc_m2m_open(struct file *file) ctx->flags = 0; ctx->in_path = FIMC_DMA; ctx->out_path = FIMC_DMA; - spin_lock_init(&ctx->slock); ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); if (IS_ERR(ctx->m2m_ctx)) { @@ -1601,7 +1559,7 @@ void fimc_unregister_m2m_device(struct fimc_dev *fimc) static void fimc_clk_put(struct fimc_dev *fimc) { int i; - for (i = 0; i < fimc->num_clocks; i++) { + for (i = 0; i < MAX_FIMC_CLOCKS; i++) { if (IS_ERR_OR_NULL(fimc->clock[i])) continue; clk_unprepare(fimc->clock[i]); @@ -1614,7 +1572,7 @@ static int fimc_clk_get(struct fimc_dev *fimc) { int i, ret; - for (i = 0; i < fimc->num_clocks; i++) { + for (i = 0; i < MAX_FIMC_CLOCKS; i++) { fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]); if (IS_ERR(fimc->clock[i])) goto err; @@ -1714,9 +1672,7 @@ static int fimc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to get IRQ resource\n"); return -ENXIO; } - fimc->irq = res->start; - fimc->num_clocks = MAX_FIMC_CLOCKS; ret = fimc_clk_get(fimc); if (ret) return ret; @@ -1725,7 +1681,7 @@ static int fimc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fimc); - ret = devm_request_irq(&pdev->dev, fimc->irq, fimc_irq_handler, + ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler, 0, pdev->name, fimc); if (ret) { dev_err(&pdev->dev, "failed to install irq (%d)\n", ret); @@ -2036,7 +1992,7 @@ static struct platform_driver fimc_driver = { int __init fimc_register_driver(void) { - return platform_driver_probe(&fimc_driver, fimc_probe); + return platform_driver_register(&fimc_driver); } void __exit fimc_unregister_driver(void) diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index a18291e648e2..193e8f603949 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h @@ -119,8 +119,6 @@ enum fimc_color_fmt { /* The hardware context state. */ #define FIMC_PARAMS (1 << 0) -#define FIMC_SRC_ADDR (1 << 1) -#define FIMC_DST_ADDR (1 << 2) #define FIMC_SRC_FMT (1 << 3) #define FIMC_DST_FMT (1 << 4) #define FIMC_DST_CROP (1 << 5) @@ -431,10 +429,8 @@ struct fimc_ctx; * @pdata: pointer to the device platform data * @variant: the IP variant information * @id: FIMC device index (0..FIMC_MAX_DEVS) - * @num_clocks: the number of clocks managed by this device instance * @clock: clocks required for FIMC operation * @regs: the mapped hardware registers - * @irq: FIMC interrupt number * @irq_queue: interrupt handler waitqueue * @v4l2_dev: root v4l2_device * @m2m: memory-to-memory V4L2 device information @@ -450,10 +446,8 @@ struct fimc_dev { struct s5p_platform_fimc *pdata; struct samsung_fimc_variant *variant; u16 id; - u16 num_clocks; struct clk *clock[MAX_FIMC_CLOCKS]; void __iomem *regs; - int irq; wait_queue_head_t irq_queue; struct v4l2_device *v4l2_dev; struct fimc_m2m_device m2m; @@ -465,7 +459,6 @@ struct fimc_dev { /** * fimc_ctx - the device context data - * @slock: spinlock protecting this data structure * @s_frame: source frame properties * @d_frame: destination frame properties * @out_order_1p: output 1-plane YCBCR order @@ -492,7 +485,6 @@ struct fimc_dev { * @ctrls_rdy: true if the control handler is initialized */ struct fimc_ctx { - spinlock_t slock; struct fimc_frame s_frame; struct fimc_frame d_frame; u32 out_order_1p; @@ -560,13 +552,13 @@ static inline bool fimc_capture_active(struct fimc_dev *fimc) return ret; } -static inline void fimc_ctx_state_lock_set(u32 state, struct fimc_ctx *ctx) +static inline void fimc_ctx_state_set(u32 state, struct fimc_ctx *ctx) { unsigned long flags; - spin_lock_irqsave(&ctx->slock, flags); + spin_lock_irqsave(&ctx->fimc_dev->slock, flags); ctx->state |= state; - spin_unlock_irqrestore(&ctx->slock, flags); + spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags); } static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx) @@ -574,9 +566,9 @@ static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx) unsigned long flags; bool ret; - spin_lock_irqsave(&ctx->slock, flags); + spin_lock_irqsave(&ctx->fimc_dev->slock, flags); ret = (ctx->state & mask) == mask; - spin_unlock_irqrestore(&ctx->slock, flags); + spin_unlock_irqrestore(&ctx->fimc_dev->slock, flags); return ret; } diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 62ed37e40149..75296a625a9d 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -214,14 +214,20 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd, return NULL; adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num); - if (!adapter) - return NULL; + if (!adapter) { + v4l2_warn(&fmd->v4l2_dev, + "Failed to get I2C adapter %d, deferring probe\n", + s_info->pdata->i2c_bus_num); + return ERR_PTR(-EPROBE_DEFER); + } sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter, s_info->pdata->board_info, NULL); if (IS_ERR_OR_NULL(sd)) { i2c_put_adapter(adapter); - v4l2_err(&fmd->v4l2_dev, "Failed to acquire subdev\n"); - return NULL; + v4l2_warn(&fmd->v4l2_dev, + "Failed to acquire subdev %s, deferring probe\n", + s_info->pdata->board_info->type); + return ERR_PTR(-EPROBE_DEFER); } v4l2_set_subdev_hostdata(sd, s_info); sd->grp_id = SENSOR_GROUP_ID; @@ -269,13 +275,22 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) fmd->num_sensors = num_clients; for (i = 0; i < num_clients; i++) { + struct v4l2_subdev *sd; + fmd->sensor[i].pdata = &pdata->isp_info[i]; ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true); if (ret) break; - fmd->sensor[i].subdev = - fimc_md_register_sensor(fmd, &fmd->sensor[i]); + sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]); ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false); + + if (!IS_ERR(sd)) { + fmd->sensor[i].subdev = sd; + } else { + fmd->sensor[i].subdev = NULL; + ret = PTR_ERR(sd); + break; + } if (ret) break; } @@ -336,22 +351,45 @@ static int csis_register_callback(struct device *dev, void *p) */ static int fimc_md_register_platform_entities(struct fimc_md *fmd) { + struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data; struct device_driver *driver; - int ret; + int ret, i; driver = driver_find(FIMC_MODULE_NAME, &platform_bus_type); - if (!driver) - return -ENODEV; + if (!driver) { + v4l2_warn(&fmd->v4l2_dev, + "%s driver not found, deffering probe\n", + FIMC_MODULE_NAME); + return -EPROBE_DEFER; + } + ret = driver_for_each_device(driver, NULL, fmd, fimc_register_callback); if (ret) return ret; + /* + * Check if there is any sensor on the MIPI-CSI2 bus and + * if not skip the s5p-csis module loading. + */ + for (i = 0; i < pdata->num_clients; i++) { + if (pdata->isp_info[i].bus_type == FIMC_MIPI_CSI2) { + ret = 1; + break; + } + } + if (!ret) + return 0; driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); - if (driver) - ret = driver_for_each_device(driver, NULL, fmd, - csis_register_callback); - return ret; + if (!driver || !try_module_get(driver->owner)) { + v4l2_warn(&fmd->v4l2_dev, + "%s driver not found, deffering probe\n", + CSIS_DRIVER_NAME); + return -EPROBE_DEFER; + } + + return driver_for_each_device(driver, NULL, fmd, + csis_register_callback); } static void fimc_md_unregister_entities(struct fimc_md *fmd) @@ -369,6 +407,7 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) if (fmd->csis[i].sd == NULL) continue; v4l2_device_unregister_subdev(fmd->csis[i].sd); + module_put(fmd->csis[i].sd->owner); fmd->csis[i].sd = NULL; } for (i = 0; i < fmd->num_sensors; i++) { @@ -744,7 +783,7 @@ static ssize_t fimc_md_sysfs_store(struct device *dev, static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO, fimc_md_sysfs_show, fimc_md_sysfs_store); -static int __devinit fimc_md_probe(struct platform_device *pdev) +static int fimc_md_probe(struct platform_device *pdev) { struct v4l2_device *v4l2_dev; struct fimc_md *fmd; @@ -841,10 +880,12 @@ static struct platform_driver fimc_md_driver = { int __init fimc_md_init(void) { int ret; + request_module("s5p-csis"); ret = fimc_register_driver(); if (ret) return ret; + return platform_driver_register(&fimc_md_driver); } void __exit fimc_md_exit(void) diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index 15466d0529c1..ff11f10fea0b 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c @@ -674,6 +674,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, { u32 cfg, tmp; struct fimc_vid_cap *vid_cap = &fimc->vid_cap; + u32 csis_data_alignment = 32; cfg = readl(fimc->regs + S5P_CIGCTRL); @@ -703,7 +704,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc, vid_cap->mf.code); return -EINVAL; } - tmp |= (cam->csi_data_align == 32) << 8; + tmp |= (csis_data_alignment == 32) << 8; writel(tmp, fimc->regs + S5P_CSIIMGFMT); diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c index f44f690397f7..2f73d9e3d0b7 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.c +++ b/drivers/media/video/s5p-fimc/mipi-csis.c @@ -127,20 +127,24 @@ struct csis_state { * multiple of 2^pix_width_alignment * @code: corresponding media bus code * @fmt_reg: S5PCSIS_CONFIG register value + * @data_alignment: MIPI-CSI data alignment in bits */ struct csis_pix_format { unsigned int pix_width_alignment; enum v4l2_mbus_pixelcode code; u32 fmt_reg; + u8 data_alignment; }; static const struct csis_pix_format s5pcsis_formats[] = { { .code = V4L2_MBUS_FMT_VYUY8_2X8, .fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT, + .data_alignment = 32, }, { .code = V4L2_MBUS_FMT_JPEG_1X8, .fmt_reg = S5PCSIS_CFG_FMT_USER(1), + .data_alignment = 32, }, }; @@ -239,7 +243,7 @@ static void s5pcsis_set_params(struct csis_state *state) s5pcsis_set_hsync_settle(state, pdata->hs_settle); val = s5pcsis_read(state, S5PCSIS_CTRL); - if (pdata->alignment == 32) + if (state->csis_fmt->data_alignment == 32) val |= S5PCSIS_CTRL_ALIGN_32BIT; else /* 24-bits */ val &= ~S5PCSIS_CTRL_ALIGN_32BIT; @@ -711,19 +715,8 @@ static struct platform_driver s5pcsis_driver = { }, }; -static int __init s5pcsis_init(void) -{ - return platform_driver_probe(&s5pcsis_driver, s5pcsis_probe); -} - -static void __exit s5pcsis_exit(void) -{ - platform_driver_unregister(&s5pcsis_driver); -} - -module_init(s5pcsis_init); -module_exit(s5pcsis_exit); +module_platform_driver(s5pcsis_driver); MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>"); -MODULE_DESCRIPTION("S5P/EXYNOS4 MIPI CSI receiver driver"); +MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/s5p-tv/mixer_drv.c b/drivers/media/video/s5p-tv/mixer_drv.c index a2c0c25ad130..edca06592883 100644 --- a/drivers/media/video/s5p-tv/mixer_drv.c +++ b/drivers/media/video/s5p-tv/mixer_drv.c @@ -461,7 +461,7 @@ static struct platform_driver mxr_driver __refdata = { static int __init mxr_init(void) { int i, ret; - static const char banner[] __initdata = KERN_INFO + static const char banner[] __initconst = KERN_INFO "Samsung TV Mixer driver, " "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; printk(banner); diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index ff2cdddf9bc6..111bfff1640d 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1105,8 +1105,6 @@ static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, if (get_user(p, &up->menu_info)) return -EFAULT; umenus = compat_ptr(p); - if (!access_ok(VERIFY_WRITE, umenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) return -EFAULT; diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 18015c0a8d31..1a71aa5fd458 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -852,7 +852,8 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change ev->u.ctrl.value64 = ctrl->cur.val64; ev->u.ctrl.minimum = ctrl->minimum; ev->u.ctrl.maximum = ctrl->maximum; - if (ctrl->type == V4L2_CTRL_TYPE_MENU) + if (ctrl->type == V4L2_CTRL_TYPE_MENU + || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) ev->u.ctrl.step = 1; else ev->u.ctrl.step = ctrl->step; @@ -1083,10 +1084,13 @@ static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval) return 0; case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: if (val < ctrl->minimum || val > ctrl->maximum) return -ERANGE; - if (ctrl->qmenu[val][0] == '\0' || - (ctrl->menu_skip_mask & (1 << val))) + if (ctrl->menu_skip_mask & (1 << val)) + return -EINVAL; + if (ctrl->type == V4L2_CTRL_TYPE_MENU && + ctrl->qmenu[val][0] == '\0') return -EINVAL; return 0; @@ -1114,6 +1118,7 @@ static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c case V4L2_CTRL_TYPE_INTEGER: case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_MENU: + case V4L2_CTRL_TYPE_INTEGER_MENU: case V4L2_CTRL_TYPE_BITMASK: case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_CTRL_CLASS: @@ -1343,7 +1348,8 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, const struct v4l2_ctrl_ops *ops, u32 id, const char *name, enum v4l2_ctrl_type type, s32 min, s32 max, u32 step, s32 def, - u32 flags, const char * const *qmenu, void *priv) + u32 flags, const char * const *qmenu, + const s64 *qmenu_int, void *priv) { struct v4l2_ctrl *ctrl; unsigned sz_extra = 0; @@ -1356,6 +1362,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, (type == V4L2_CTRL_TYPE_INTEGER && step == 0) || (type == V4L2_CTRL_TYPE_BITMASK && max == 0) || (type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) || + (type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL) || (type == V4L2_CTRL_TYPE_STRING && max == 0)) { handler_set_err(hdl, -ERANGE); return NULL; @@ -1366,6 +1373,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, } if ((type == V4L2_CTRL_TYPE_INTEGER || type == V4L2_CTRL_TYPE_MENU || + type == V4L2_CTRL_TYPE_INTEGER_MENU || type == V4L2_CTRL_TYPE_BOOLEAN) && (def < min || def > max)) { handler_set_err(hdl, -ERANGE); @@ -1400,7 +1408,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl, ctrl->minimum = min; ctrl->maximum = max; ctrl->step = step; - ctrl->qmenu = qmenu; + if (type == V4L2_CTRL_TYPE_MENU) + ctrl->qmenu = qmenu; + else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) + ctrl->qmenu_int = qmenu_int; ctrl->priv = priv; ctrl->cur.val = ctrl->val = ctrl->default_value = def; @@ -1427,6 +1438,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl *ctrl; const char *name = cfg->name; const char * const *qmenu = cfg->qmenu; + const s64 *qmenu_int = cfg->qmenu_int; enum v4l2_ctrl_type type = cfg->type; u32 flags = cfg->flags; s32 min = cfg->min; @@ -1438,18 +1450,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl, v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step, &def, &flags); - is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU); + is_menu = (cfg->type == V4L2_CTRL_TYPE_MENU || + cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU); if (is_menu) WARN_ON(step); else WARN_ON(cfg->menu_skip_mask); - if (is_menu && qmenu == NULL) + if (cfg->type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) qmenu = v4l2_ctrl_get_menu(cfg->id); + else if (cfg->type == V4L2_CTRL_TYPE_INTEGER_MENU && + qmenu_int == NULL) { + handler_set_err(hdl, -EINVAL); + return NULL; + } ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name, type, min, max, is_menu ? cfg->menu_skip_mask : step, - def, flags, qmenu, priv); + def, flags, qmenu, qmenu_int, priv); if (ctrl) ctrl->is_private = cfg->is_private; return ctrl; @@ -1466,12 +1484,13 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, u32 flags; v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags); - if (type == V4L2_CTRL_TYPE_MENU) { + if (type == V4L2_CTRL_TYPE_MENU + || type == V4L2_CTRL_TYPE_INTEGER_MENU) { handler_set_err(hdl, -EINVAL); return NULL; } return v4l2_ctrl_new(hdl, ops, id, name, type, - min, max, step, def, flags, NULL, NULL); + min, max, step, def, flags, NULL, NULL, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_std); @@ -1493,7 +1512,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, return NULL; } return v4l2_ctrl_new(hdl, ops, id, name, type, - 0, max, mask, def, flags, qmenu, NULL); + 0, max, mask, def, flags, qmenu, NULL, NULL); } EXPORT_SYMBOL(v4l2_ctrl_new_std_menu); @@ -1659,6 +1678,9 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl, case V4L2_CTRL_TYPE_MENU: printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]); break; + case V4L2_CTRL_TYPE_INTEGER_MENU: + printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]); + break; case V4L2_CTRL_TYPE_BITMASK: printk(KERN_CONT "0x%08x", ctrl->cur.val); break; @@ -1795,7 +1817,8 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc) qc->minimum = ctrl->minimum; qc->maximum = ctrl->maximum; qc->default_value = ctrl->default_value; - if (ctrl->type == V4L2_CTRL_TYPE_MENU) + if (ctrl->type == V4L2_CTRL_TYPE_MENU + || ctrl->type == V4L2_CTRL_TYPE_INTEGER_MENU) qc->step = 1; else qc->step = ctrl->step; @@ -1825,16 +1848,33 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm) qm->reserved = 0; /* Sanity checks */ - if (ctrl->qmenu == NULL || - i < ctrl->minimum || i > ctrl->maximum) + switch (ctrl->type) { + case V4L2_CTRL_TYPE_MENU: + if (ctrl->qmenu == NULL) + return -EINVAL; + break; + case V4L2_CTRL_TYPE_INTEGER_MENU: + if (ctrl->qmenu_int == NULL) + return -EINVAL; + break; + default: + return -EINVAL; + } + + if (i < ctrl->minimum || i > ctrl->maximum) return -EINVAL; + /* Use mask to see if this menu item should be skipped */ if (ctrl->menu_skip_mask & (1 << i)) return -EINVAL; /* Empty menu items should also be skipped */ - if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0') - return -EINVAL; - strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); + if (ctrl->type == V4L2_CTRL_TYPE_MENU) { + if (ctrl->qmenu[i] == NULL || ctrl->qmenu[i][0] == '\0') + return -EINVAL; + strlcpy(qm->name, ctrl->qmenu[i], sizeof(qm->name)); + } else { + qm->value = ctrl->qmenu_int[i]; + } return 0; } EXPORT_SYMBOL(v4l2_querymenu); @@ -1996,7 +2036,8 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs return class_check(hdl, cs->ctrl_class); if (cs->count > ARRAY_SIZE(helper)) { - helpers = kmalloc(sizeof(helper[0]) * cs->count, GFP_KERNEL); + helpers = kmalloc_array(cs->count, sizeof(helper[0]), + GFP_KERNEL); if (helpers == NULL) return -ENOMEM; } @@ -2218,7 +2259,8 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, return class_check(hdl, cs->ctrl_class); if (cs->count > ARRAY_SIZE(helper)) { - helpers = kmalloc(sizeof(helper[0]) * cs->count, GFP_KERNEL); + helpers = kmalloc_array(cs->count, sizeof(helper[0]), + GFP_KERNEL); if (!helpers) return -ENOMEM; } diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 6fe88e965a8c..268d80584101 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c @@ -35,14 +35,9 @@ static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) { #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - /* Allocate try format and crop in the same memory block */ - fh->try_fmt = kzalloc((sizeof(*fh->try_fmt) + sizeof(*fh->try_crop)) - * sd->entity.num_pads, GFP_KERNEL); - if (fh->try_fmt == NULL) + fh->pad = kzalloc(sizeof(*fh->pad) * sd->entity.num_pads, GFP_KERNEL); + if (fh->pad == NULL) return -ENOMEM; - - fh->try_crop = (struct v4l2_rect *) - (fh->try_fmt + sd->entity.num_pads); #endif return 0; } @@ -50,9 +45,8 @@ static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd) static void subdev_fh_free(struct v4l2_subdev_fh *fh) { #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - kfree(fh->try_fmt); - fh->try_fmt = NULL; - fh->try_crop = NULL; + kfree(fh->pad); + fh->pad = NULL; #endif } @@ -234,6 +228,8 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) case VIDIOC_SUBDEV_G_CROP: { struct v4l2_subdev_crop *crop = arg; + struct v4l2_subdev_selection sel; + int rval; if (crop->which != V4L2_SUBDEV_FORMAT_TRY && crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) @@ -242,11 +238,27 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (crop->pad >= sd->entity.num_pads) return -EINVAL; - return v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop); + rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop); + if (rval != -ENOIOCTLCMD) + return rval; + + memset(&sel, 0, sizeof(sel)); + sel.which = crop->which; + sel.pad = crop->pad; + sel.target = V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL; + + rval = v4l2_subdev_call( + sd, pad, get_selection, subdev_fh, &sel); + + crop->rect = sel.r; + + return rval; } case VIDIOC_SUBDEV_S_CROP: { struct v4l2_subdev_crop *crop = arg; + struct v4l2_subdev_selection sel; + int rval; if (crop->which != V4L2_SUBDEV_FORMAT_TRY && crop->which != V4L2_SUBDEV_FORMAT_ACTIVE) @@ -255,7 +267,22 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (crop->pad >= sd->entity.num_pads) return -EINVAL; - return v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop); + rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop); + if (rval != -ENOIOCTLCMD) + return rval; + + memset(&sel, 0, sizeof(sel)); + sel.which = crop->which; + sel.pad = crop->pad; + sel.target = V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL; + sel.r = crop->rect; + + rval = v4l2_subdev_call( + sd, pad, set_selection, subdev_fh, &sel); + + crop->rect = sel.r; + + return rval; } case VIDIOC_SUBDEV_ENUM_MBUS_CODE: { @@ -293,6 +320,34 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh, fie); } + + case VIDIOC_SUBDEV_G_SELECTION: { + struct v4l2_subdev_selection *sel = arg; + + if (sel->which != V4L2_SUBDEV_FORMAT_TRY && + sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (sel->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call( + sd, pad, get_selection, subdev_fh, sel); + } + + case VIDIOC_SUBDEV_S_SELECTION: { + struct v4l2_subdev_selection *sel = arg; + + if (sel->which != V4L2_SUBDEV_FORMAT_TRY && + sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (sel->pad >= sd->entity.num_pads) + return -EINVAL; + + return v4l2_subdev_call( + sd, pad, set_selection, subdev_fh, sel); + } #endif default: return v4l2_subdev_call(sd, core, ioctl, cmd, arg); diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index de4fa4eb8844..ffdf59cfe405 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -1129,6 +1129,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_queue *q, poll_table *wait) { + unsigned long req_events = poll_requested_events(wait); struct videobuf_buffer *buf = NULL; unsigned int rc = 0; @@ -1137,7 +1138,7 @@ unsigned int videobuf_poll_stream(struct file *file, if (!list_empty(&q->stream)) buf = list_entry(q->stream.next, struct videobuf_buffer, stream); - } else { + } else if (req_events & (POLLIN | POLLRDNORM)) { if (!q->reading) __videobuf_read_start(q); if (!q->reading) { diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 2e8f1df775b6..3786d88183eb 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c @@ -19,6 +19,9 @@ #include <linux/slab.h> #include <linux/sched.h> +#include <media/v4l2-dev.h> +#include <media/v4l2-fh.h> +#include <media/v4l2-event.h> #include <media/videobuf2-core.h> static int debug; @@ -1642,32 +1645,46 @@ static int __vb2_cleanup_fileio(struct vb2_queue *q); * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor * will be reported as available for writing. * + * If the driver uses struct v4l2_fh, then vb2_poll() will also check for any + * pending events. + * * The return values from this function are intended to be directly returned * from poll handler in driver. */ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) { - unsigned long flags; - unsigned int ret; + struct video_device *vfd = video_devdata(file); + unsigned long req_events = poll_requested_events(wait); struct vb2_buffer *vb = NULL; + unsigned int res = 0; + unsigned long flags; + + if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { + struct v4l2_fh *fh = file->private_data; + + if (v4l2_event_pending(fh)) + res = POLLPRI; + else if (req_events & POLLPRI) + poll_wait(file, &fh->wait, wait); + } /* * Start file I/O emulator only if streaming API has not been used yet. */ if (q->num_buffers == 0 && q->fileio == NULL) { - if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ)) { - ret = __vb2_init_fileio(q, 1); - if (ret) - return POLLERR; + if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && + (req_events & (POLLIN | POLLRDNORM))) { + if (__vb2_init_fileio(q, 1)) + return res | POLLERR; } - if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE)) { - ret = __vb2_init_fileio(q, 0); - if (ret) - return POLLERR; + if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) && + (req_events & (POLLOUT | POLLWRNORM))) { + if (__vb2_init_fileio(q, 0)) + return res | POLLERR; /* * Write to OUTPUT queue can be done immediately. */ - return POLLOUT | POLLWRNORM; + return res | POLLOUT | POLLWRNORM; } } @@ -1675,7 +1692,7 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) * There is nothing to wait for if no buffers have already been queued. */ if (list_empty(&q->queued_list)) - return POLLERR; + return res | POLLERR; poll_wait(file, &q->done_wq, wait); @@ -1690,10 +1707,11 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) if (vb && (vb->state == VB2_BUF_STATE_DONE || vb->state == VB2_BUF_STATE_ERROR)) { - return (V4L2_TYPE_IS_OUTPUT(q->type)) ? POLLOUT | POLLWRNORM : - POLLIN | POLLRDNORM; + return (V4L2_TYPE_IS_OUTPUT(q->type)) ? + res | POLLOUT | POLLWRNORM : + res | POLLIN | POLLRDNORM; } - return 0; + return res; } EXPORT_SYMBOL_GPL(vb2_poll); diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5e8b0710105b..ff39eb2f2d7b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -177,6 +177,7 @@ struct vivi_dev { struct v4l2_ctrl *menu; struct v4l2_ctrl *string; struct v4l2_ctrl *bitmask; + struct v4l2_ctrl *int_menu; spinlock_t slock; struct mutex mutex; @@ -503,6 +504,10 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) dev->boolean->cur.val, dev->menu->qmenu[dev->menu->cur.val], dev->string->cur.string); + snprintf(str, sizeof(str), " integer_menu %lld, value %d ", + dev->int_menu->qmenu_int[dev->int_menu->cur.val], + dev->int_menu->cur.val); + gen_text(dev, vbuf, line++ * 16, 16, str); mutex_unlock(&dev->ctrl_handler.lock); gen_text(dev, vbuf, line++ * 16, 16, str); if (dev->button_pressed) { @@ -1039,17 +1044,10 @@ static unsigned int vivi_poll(struct file *file, struct poll_table_struct *wait) { struct vivi_dev *dev = video_drvdata(file); - struct v4l2_fh *fh = file->private_data; struct vb2_queue *q = &dev->vb_vidq; - unsigned int res; dprintk(dev, 1, "%s\n", __func__); - res = vb2_poll(q, file, wait); - if (v4l2_event_pending(fh)) - res |= POLLPRI; - else - poll_wait(file, &fh->wait, wait); - return res; + return vb2_poll(q, file, wait); } static int vivi_close(struct file *file) @@ -1165,6 +1163,22 @@ static const struct v4l2_ctrl_config vivi_ctrl_bitmask = { .step = 0, }; +static const s64 vivi_ctrl_int_menu_values[] = { + 1, 1, 2, 3, 5, 8, 13, 21, 42, +}; + +static const struct v4l2_ctrl_config vivi_ctrl_int_menu = { + .ops = &vivi_ctrl_ops, + .id = VIVI_CID_CUSTOM_BASE + 7, + .name = "Integer menu", + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .min = 1, + .max = 8, + .def = 4, + .menu_skip_mask = 0x02, + .qmenu_int = vivi_ctrl_int_menu_values, +}; + static const struct v4l2_file_operations vivi_fops = { .owner = THIS_MODULE, .open = v4l2_fh_open, @@ -1275,6 +1289,7 @@ static int __init vivi_create_instance(int inst) dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL); dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL); dev->bitmask = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_bitmask, NULL); + dev->int_menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int_menu, NULL); if (hdl->error) { ret = hdl->error; goto unreg_dev; diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 4c09ab781ec3..c57310931810 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1131,8 +1131,14 @@ static int setup_fbuffer(struct zoran_fh *fh, } -static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height, - struct v4l2_clip __user *clips, int clipcount, void __user *bitmap) +static int setup_window(struct zoran_fh *fh, + int x, + int y, + int width, + int height, + struct v4l2_clip __user *clips, + unsigned int clipcount, + void __user *bitmap) { struct zoran *zr = fh->zr; struct v4l2_clip *vcp = NULL; @@ -1155,6 +1161,14 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height return -EINVAL; } + if (clipcount > 2048) { + dprintk(1, + KERN_ERR + "%s: %s - invalid clipcount\n", + ZR_DEVNAME(zr), __func__); + return -EINVAL; + } + /* * The video front end needs 4-byte alinged line sizes, we correct that * silently here if necessary @@ -1218,7 +1232,7 @@ static int setup_window(struct zoran_fh *fh, int x, int y, int width, int height (width * height + 7) / 8)) { return -EFAULT; } - } else if (clipcount > 0) { + } else if (clipcount) { /* write our own bitmap from the clips */ vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4)); if (vcp == NULL) { diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 9f1f27e7c86e..4511420849bc 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -269,7 +269,7 @@ out: return ret; } -static inline unsigned long calc_vm_may_flags(unsigned long prot) +static inline vm_flags_t calc_vm_may_flags(unsigned long prot) { return _calc_vm_trans(prot, PROT_READ, VM_MAYREAD) | _calc_vm_trans(prot, PROT_WRITE, VM_MAYWRITE) | diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c index 1075fb1df0d9..b9670ee41b4e 100644 --- a/drivers/staging/media/as102/as102_fw.c +++ b/drivers/staging/media/as102/as102_fw.c @@ -230,11 +230,8 @@ int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap) pr_info("%s: firmware: %s loaded with success\n", DRIVER_NAME, fw2); error: - /* free data buffer */ kfree(cmd_buf); - /* release firmware if needed */ - if (firmware != NULL) - release_firmware(firmware); + release_firmware(firmware); LEAVE(); return errno; diff --git a/drivers/staging/media/lirc/lirc_imon.c b/drivers/staging/media/lirc/lirc_imon.c index 5f7f8cd3a661..083219da3a39 100644 --- a/drivers/staging/media/lirc/lirc_imon.c +++ b/drivers/staging/media/lirc/lirc_imon.c @@ -70,10 +70,6 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, static int ir_open(void *data); static void ir_close(void *data); -/* Driver init/exit prototypes */ -static int __init imon_init(void); -static void __exit imon_exit(void); - /*** G L O B A L S ***/ #define IMON_DATA_BUF_SZ 35 diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c index 74421043b954..d5bc35aea1c1 100644 --- a/drivers/staging/media/lirc/lirc_sasem.c +++ b/drivers/staging/media/lirc/lirc_sasem.c @@ -80,10 +80,6 @@ static ssize_t vfd_write(struct file *file, const char *buf, static int ir_open(void *data); static void ir_close(void *data); -/* Driver init/exit prototypes */ -static int __init sasem_init(void); -static void __exit sasem_exit(void); - /*** G L O B A L S ***/ #define SASEM_DATA_BUF_SZ 32 diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index d776adb2da67..104ae9c81251 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -543,11 +543,11 @@ done: return ret; } +/* called with &queue_irqlock held.. */ static struct uvc_buffer * uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { struct uvc_buffer *nextbuf; - unsigned long flags; if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && buf->buf.length != buf->buf.bytesused) { @@ -556,14 +556,12 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) return buf; } - spin_lock_irqsave(&queue->irqlock, flags); list_del(&buf->queue); if (!list_empty(&queue->irqqueue)) nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); else nextbuf = NULL; - spin_unlock_irqrestore(&queue->irqlock, flags); buf->buf.sequence = queue->sequence++; do_gettimeofday(&buf->buf.timestamp); diff --git a/include/linux/v4l2-subdev.h b/include/linux/v4l2-subdev.h index ed29cbbebfef..812019ee1e06 100644 --- a/include/linux/v4l2-subdev.h +++ b/include/linux/v4l2-subdev.h @@ -123,6 +123,43 @@ struct v4l2_subdev_frame_interval_enum { __u32 reserved[9]; }; +#define V4L2_SUBDEV_SEL_FLAG_SIZE_GE (1 << 0) +#define V4L2_SUBDEV_SEL_FLAG_SIZE_LE (1 << 1) +#define V4L2_SUBDEV_SEL_FLAG_KEEP_CONFIG (1 << 2) + +/* active cropping area */ +#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL 0x0000 +/* cropping bounds */ +#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS 0x0002 +/* current composing area */ +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL 0x0100 +/* composing bounds */ +#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS 0x0102 + + +/** + * struct v4l2_subdev_selection - selection info + * + * @which: either V4L2_SUBDEV_FORMAT_ACTIVE or V4L2_SUBDEV_FORMAT_TRY + * @pad: pad number, as reported by the media API + * @target: selection target, used to choose one of possible rectangles + * @flags: constraint flags + * @r: coordinates of the selection window + * @reserved: for future use, set to zero for now + * + * Hardware may use multiple helper windows to process a video stream. + * The structure is used to exchange this selection areas between + * an application and a driver. + */ +struct v4l2_subdev_selection { + __u32 which; + __u32 pad; + __u32 target; + __u32 flags; + struct v4l2_rect r; + __u32 reserved[8]; +}; + #define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format) #define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format) #define VIDIOC_SUBDEV_G_FRAME_INTERVAL \ @@ -137,5 +174,9 @@ struct v4l2_subdev_frame_interval_enum { _IOWR('V', 75, struct v4l2_subdev_frame_interval_enum) #define VIDIOC_SUBDEV_G_CROP _IOWR('V', 59, struct v4l2_subdev_crop) #define VIDIOC_SUBDEV_S_CROP _IOWR('V', 60, struct v4l2_subdev_crop) +#define VIDIOC_SUBDEV_G_SELECTION \ + _IOWR('V', 61, struct v4l2_subdev_selection) +#define VIDIOC_SUBDEV_S_SELECTION \ + _IOWR('V', 62, struct v4l2_subdev_selection) #endif diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index c9c9a4680cc5..e69cacc9e9ea 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1151,6 +1151,7 @@ enum v4l2_ctrl_type { V4L2_CTRL_TYPE_CTRL_CLASS = 6, V4L2_CTRL_TYPE_STRING = 7, V4L2_CTRL_TYPE_BITMASK = 8, + V4L2_CTRL_TYPE_INTEGER_MENU = 9, }; /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ @@ -1170,7 +1171,10 @@ struct v4l2_queryctrl { struct v4l2_querymenu { __u32 id; __u32 index; - __u8 name[32]; /* Whatever */ + union { + __u8 name[32]; /* Whatever */ + __s64 value; + }; __u32 reserved; }; diff --git a/include/media/rc-map.h b/include/media/rc-map.h index 8db6741c1256..88583a6ff7f2 100644 --- a/include/media/rc-map.h +++ b/include/media/rc-map.h @@ -113,6 +113,7 @@ void rc_map_init(void); #define RC_MAP_LME2510 "rc-lme2510" #define RC_MAP_MANLI "rc-manli" #define RC_MAP_MEDION_X10 "rc-medion-x10" +#define RC_MAP_MEDION_X10_DIGITAINER "rc-medion-x10-digitainer" #define RC_MAP_MSI_DIGIVOX_II "rc-msi-digivox-ii" #define RC_MAP_MSI_DIGIVOX_III "rc-msi-digivox-iii" #define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus" diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 11e67562b3ac..33907a969752 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -129,7 +129,10 @@ struct v4l2_ctrl { u32 step; u32 menu_skip_mask; }; - const char * const *qmenu; + union { + const char * const *qmenu; + const s64 *qmenu_int; + }; unsigned long flags; union { s32 val; @@ -219,6 +222,7 @@ struct v4l2_ctrl_config { u32 flags; u32 menu_skip_mask; const char * const *qmenu; + const s64 *qmenu_int; unsigned int is_private:1; }; diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index f0f3358d1b1b..7e850355a6f0 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -466,6 +466,10 @@ struct v4l2_subdev_pad_ops { struct v4l2_subdev_crop *crop); int (*get_crop)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, struct v4l2_subdev_crop *crop); + int (*get_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel); + int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, + struct v4l2_subdev_selection *sel); }; struct v4l2_subdev_ops { @@ -541,7 +545,7 @@ struct v4l2_subdev { #define media_entity_to_v4l2_subdev(ent) \ container_of(ent, struct v4l2_subdev, entity) #define vdev_to_v4l2_subdev(vdev) \ - video_get_drvdata(vdev) + ((struct v4l2_subdev *)video_get_drvdata(vdev)) /* * Used for storing subdev information per file handle @@ -549,8 +553,11 @@ struct v4l2_subdev { struct v4l2_subdev_fh { struct v4l2_fh vfh; #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) - struct v4l2_mbus_framefmt *try_fmt; - struct v4l2_rect *try_crop; + struct { + struct v4l2_mbus_framefmt try_fmt; + struct v4l2_rect try_crop; + struct v4l2_rect try_compose; + } *pad; #endif }; @@ -558,17 +565,19 @@ struct v4l2_subdev_fh { container_of(fh, struct v4l2_subdev_fh, vfh) #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) -static inline struct v4l2_mbus_framefmt * -v4l2_subdev_get_try_format(struct v4l2_subdev_fh *fh, unsigned int pad) -{ - return &fh->try_fmt[pad]; -} - -static inline struct v4l2_rect * -v4l2_subdev_get_try_crop(struct v4l2_subdev_fh *fh, unsigned int pad) -{ - return &fh->try_crop[pad]; -} +#define __V4L2_SUBDEV_MK_GET_TRY(rtype, fun_name, field_name) \ + static inline struct rtype * \ + v4l2_subdev_get_try_##fun_name(struct v4l2_subdev_fh *fh, \ + unsigned int pad) \ + { \ + BUG_ON(unlikely(pad >= vdev_to_v4l2_subdev( \ + fh->vfh.vdev)->entity.num_pads)); \ + return &fh->pad[pad].field_name; \ + } + +__V4L2_SUBDEV_MK_GET_TRY(v4l2_mbus_framefmt, format, try_fmt) +__V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, crop, try_compose) +__V4L2_SUBDEV_MK_GET_TRY(v4l2_rect, compose, try_compose) #endif extern const struct v4l2_file_operations v4l2_subdev_fops; diff --git a/kernel/kfifo.c b/kernel/kfifo.c index c744b88c44e2..59dcf5b81d24 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -402,6 +402,7 @@ unsigned int __kfifo_max_r(unsigned int len, size_t recsize) return max; return len; } +EXPORT_SYMBOL(__kfifo_max_r); #define __KFIFO_PEEK(data, out, mask) \ ((data)[(out) & (mask)]) |